@imenam/mcp-documentor 1.0.104 → 1.0.105

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -46,9 +46,9 @@ From the repo you want to document, generate a ready-to-fill `.mcp.json` in the
46
46
  npx @imenam/mcp-documentor --claude-setup-mcp
47
47
  ```
48
48
 
49
- It creates the `mcp-documentor` entry with the usual environment variables as empty placeholders —
50
- an empty variable is simply inactive, so the generated config runs as-is and you only fill in what
51
- you need. An existing `.mcp.json` is merged, other servers are preserved, and an existing
49
+ It creates the `mcp-documentor` entry with `DATA_DIR` set to `<current folder>/.docs-data` and the
50
+ other environment variables as empty placeholders — an empty variable is simply inactive, so the
51
+ generated config runs as-is and you only fill in what you need. An existing `.mcp.json` is merged, other servers are preserved, and an existing
52
52
  `mcp-documentor` entry is only replaced when `--force` is passed.
53
53
 
54
54
  Two flags let you pick how the GUI is exposed straight from the command line, instead of editing
@@ -75,6 +75,7 @@ Add to your MCP client config (e.g. Cursor `mcp.json`):
75
75
  "command": "npx",
76
76
  "args": ["-y", "@imenam/mcp-documentor"],
77
77
  "env": {
78
+ "DATA_DIR": "/path/to/your/data",
78
79
  "OPENAI_API_KEY": "sk-..."
79
80
  }
80
81
  }
@@ -91,7 +92,7 @@ Add to your MCP client config (e.g. Cursor `mcp.json`):
91
92
  | `PROXY_URL` | No | URL of the proxy server: it allocates the port and mounts the GUI under `APP_PATH` |
92
93
  | `APP_PORT` | No | Local port used **when `PROXY_URL` is unset**: the GUI is served directly at `http://localhost:<port>`, at the root. Lets you use the interface without the central hub. `PROXY_URL` wins if both are set; with neither, the GUI is disabled and the MCP tools still work |
93
94
  | `APP_GROUP` | No | Groups the app under a collapsible section (folded by default) in the proxy dashboard. Apps sharing the same value appear together; if unset, the app lands in the default "ungrouped" section |
94
- | `MCP_DATA_DIR` | No | Overrides the default data directory (see Data storage) |
95
+ | `DATA_DIR` | Yes | Data directory, no default (see [Data Storage](#data-storage)). The server refuses to start without it. The MCP Gateway Manager fills it automatically |
95
96
  | `MCP_LOG_DIR` | No | Overrides the log directory of both the server and the GUI worker (default: `<package>/.docs-data/logs`). Must be set in the MCP client config — the package `.env` is loaded after the logger starts |
96
97
  | `MCP_DOCUMENTOR_CODE_ROOT` | No | Seeds the machine's default code root the first time a data directory starts (`--claude-setup-mcp` fills it with the current folder). Afterwards code roots are set in the GUI or with `set_code_root` (see [Portable tracked-file paths](#portable-tracked-file-paths)) |
97
98
  | `MCP_DOCUMENTOR_CODE_TOKEN` | No | GitHub token used to read the code of projects tracking a GitHub branch. The only place it is set: neither the GUI nor the agent can change it |
@@ -164,7 +165,7 @@ The GUI serves uploaded images under `/api/images/<project>/<file>`, where `<pro
164
165
  }
165
166
  ```
166
167
 
167
- The tool copies the file into `.docs-data/projects/{project}/assets/` and returns the ready-to-use markdown snippet.
168
+ The tool copies the file into `<DATA_DIR>/projects/{project}/assets/` and returns the ready-to-use markdown snippet.
168
169
 
169
170
  **Via the GUI editor** — click the **🖼 Image** button in the editor toolbar to open the image panel:
170
171
  - **Upload tab** — pick a local file; it is uploaded automatically and the markdown link is inserted at the cursor position
@@ -294,13 +295,13 @@ The feature is **opt-in**: with no code root configured, behaviour is unchanged
294
295
  Docs created before this feature store absolute paths. Convert them in one shot with the bundled `mcp-documentor-migrate-paths`:
295
296
 
296
297
  ```bash
297
- MCP_DATA_DIR="/path/to/your/data" \
298
+ DATA_DIR="/path/to/your/data" \
298
299
  npx -p @imenam/mcp-documentor mcp-documentor-migrate-paths --dry-run
299
300
  ```
300
301
 
301
302
  It uses the code roots stored for that data directory, so set them first.
302
303
 
303
- Review the report (`converted` / `kept absolute (outside root)` / `projects skipped`), then re-run without `--dry-run`. Finally publish with `sync_docs` (never commit the data dir by hand). The data dir is resolved like the server: `--data-dir` flag → `MCP_DATA_DIR` → package-relative fallback.
304
+ Review the report (`converted` / `kept absolute (outside root)` / `projects skipped`), then re-run without `--dry-run`. Finally publish with `sync_docs` (never commit the data dir by hand). The data dir is the `--data-dir` flag, else `DATA_DIR`; without either, the script stops.
304
305
 
305
306
  This is a **one-time** operation, and must run on the machine whose OS/filesystem **created** the stored absolute paths (path semantics differ between Windows and POSIX). Once migrated and synced, every other machine just `pull_docs` and sets its own code roots — no migration needed.
306
307
 
@@ -360,7 +361,7 @@ Everything else is content-addressed: a commit's tree is cached by its sha for t
360
361
 
361
362
  ## Data Storage
362
363
 
363
- By default, data lives under **`.docs-data`** next to the resolved package root (the folder that contains `package.json` for the running install). Set **`MCP_DATA_DIR`** to use another directory. Contents include projects, SQLite/embeddings, and logs under `.docs-data/logs`. This tree is **not** part of the npm package; it is created at runtime.
364
+ Data lives in **`DATA_DIR`**, which is required and has no default; a relative path is resolved against the working directory, and the folder is created if missing. Contents include projects and SQLite/embeddings. This tree is **not** part of the npm package; it is created at runtime.
364
365
 
365
366
  There is no server-side "active project": every MCP tool call names its project, and the GUI's selector only changes what that browser displays (kept in the URL and in `localStorage`). The open and closed folders of each project's navigation tree are also kept in `localStorage`, so a reload restores them. A legacy `currentProject` left in `config.json` is dropped on first read. GitHub sync settings live in environment variables, not on disk.
366
367
 
@@ -39,7 +39,7 @@ function buildServerEntry(codeRoot, exposure) {
39
39
  APP_GROUP: capitalize(folder),
40
40
  APP_NAME: `Documentor ${toDisplayName(folder)}`,
41
41
  APP_PATH: `/documentor-${folder}`,
42
- MCP_DATA_DIR: "",
42
+ DATA_DIR: toPosixPath(path.join(codeRoot, ".docs-data")),
43
43
  MCP_LOG_DIR: "",
44
44
  MCP_DOCUMENTOR_CODE_ROOT: toPosixPath(codeRoot),
45
45
  MCP_DOCUMENTOR_OPENAI_API_KEY: "",
@@ -56,7 +56,7 @@ const GENERATED_VARS = [
56
56
  ["APP_GROUP", "groupe d'affichage dans le dashboard du proxy"],
57
57
  ["APP_NAME", "nom affiché de la GUI dans le dashboard du proxy"],
58
58
  ["APP_PATH", "chemin de montage de la GUI derrière le proxy"],
59
- ["MCP_DATA_DIR", "répertoire de données (défaut : celui du package)"],
59
+ ["DATA_DIR", "répertoire de données, obligatoire (pré-rempli)"],
60
60
  ["MCP_LOG_DIR", "répertoire des logs"],
61
61
  ["MCP_DOCUMENTOR_CODE_ROOT", "racine du code par défaut (pré-remplie avec le répertoire courant), reprise au premier démarrage puis réglable dans la GUI"],
62
62
  ["MCP_DOCUMENTOR_OPENAI_API_KEY", "clé OpenAI (active search_docs)"],
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Storage folder read from the required DATA_DIR variable, resolved against the
3
+ * working directory and created when missing.
4
+ */
5
+ export declare function resolveDataDir(env?: NodeJS.ProcessEnv): string;
@@ -0,0 +1,15 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ /**
4
+ * Storage folder read from the required DATA_DIR variable, resolved against the
5
+ * working directory and created when missing.
6
+ */
7
+ export function resolveDataDir(env = process.env) {
8
+ const rawDataDir = env.DATA_DIR?.trim();
9
+ if (!rawDataDir) {
10
+ throw new Error("DATA_DIR is not set. It is the folder where the documentation projects, the search index and the history are stored.");
11
+ }
12
+ const dataDir = path.resolve(rawDataDir);
13
+ fs.mkdirSync(dataDir, { recursive: true });
14
+ return dataDir;
15
+ }
@@ -21,9 +21,9 @@ export interface SyncConfig {
21
21
  token?: string;
22
22
  }
23
23
  export declare class StorageEngine {
24
- private rootDir;
24
+ private dataDir;
25
25
  private historyStore?;
26
- constructor(rootDir: string);
26
+ constructor(dataDir: string);
27
27
  setHistoryStore(store: HistoryStore): void;
28
28
  getDataDir(): string;
29
29
  /**
@@ -19,17 +19,16 @@ function withoutUndefined(value) {
19
19
  return Object.fromEntries(Object.entries(value).filter(([, v]) => v !== undefined));
20
20
  }
21
21
  export class StorageEngine {
22
- rootDir;
22
+ dataDir;
23
23
  historyStore;
24
- constructor(rootDir) {
25
- this.rootDir = rootDir;
24
+ constructor(dataDir) {
25
+ this.dataDir = dataDir;
26
26
  }
27
27
  setHistoryStore(store) {
28
28
  this.historyStore = store;
29
29
  }
30
30
  getDataDir() {
31
- const envDir = process.env.MCP_DATA_DIR;
32
- return envDir && envDir.trim() !== "" ? envDir : path.join(this.rootDir, ".docs-data");
31
+ return this.dataDir;
33
32
  }
34
33
  /**
35
34
  * There is no "current project" fallback: every caller names the project it
@@ -14,6 +14,7 @@ const execFileAsync = promisify(execFile);
14
14
  import { fileURLToPath } from "url";
15
15
  import { createLogger, setupLogging } from "@imenam/mcp-gui-interface";
16
16
  import { resolveLogDir } from "./core/log-dir.js";
17
+ import { resolveDataDir } from "./core/data-dir.js";
17
18
  import { isLogSource, logFileInfo, readGitHubLog, readServerLog } from "./core/log-reader.js";
18
19
  import { isSafeSegment, PublicationStore } from "./core/publication-store.js";
19
20
  import { CommentStore, MAX_AUTHOR_LENGTH, MAX_BODY_LENGTH, MAX_QUOTE_LENGTH, } from "./core/comment-store.js";
@@ -32,7 +33,7 @@ function findProjectRoot(startDir) {
32
33
  return startDir;
33
34
  }
34
35
  const rootDir = findProjectRoot(__dirname);
35
- const dataDir = process.env.MCP_DATA_DIR?.trim() || path.join(rootDir, ".docs-data");
36
+ const dataDir = resolveDataDir();
36
37
  const staticRoot = path.join(rootDir, "gui/dist");
37
38
  const absoluteStaticRoot = path.resolve(staticRoot);
38
39
  const configuredAppPath = process.env.APP_PATH || "/documentor-gui";
@@ -299,7 +300,7 @@ app.get("/api/configurations", async (c) => {
299
300
  const currentModel = configRes.data?.model || "text-embedding-3-small";
300
301
  return c.json([
301
302
  {
302
- key: "MCP_DATA_DIR",
303
+ key: "DATA_DIR",
303
304
  label: "Data Directory",
304
305
  type: "text",
305
306
  description: "Répertoire de stockage des documentations",
package/dist/src/index.js CHANGED
@@ -11,6 +11,7 @@ import { GuiLauncher, createLogger, setupLogging } from "@imenam/mcp-gui-interfa
11
11
  import { resolveLogDir } from "./core/log-dir.js";
12
12
  import { initGitHubLog, runTriggeredBy } from "./core/github-log.js";
13
13
  import { StorageEngine } from "./core/storage-engine.js";
14
+ import { resolveDataDir } from "./core/data-dir.js";
14
15
  import { EmbeddingStore } from "./core/embedding-store.js";
15
16
  import { EmbeddingEngine } from "./core/embedding-engine.js";
16
17
  import { createDoc, slugify } from "./tools/create-doc.js";
@@ -100,7 +101,7 @@ function getConfig() {
100
101
  };
101
102
  }
102
103
  getConfig();
103
- const storageEngine = new StorageEngine(rootDir);
104
+ const storageEngine = new StorageEngine(resolveDataDir());
104
105
  const embeddingStore = new EmbeddingStore();
105
106
  const embeddingEngine = new EmbeddingEngine(embeddingStore);
106
107
  for (const project of storageEngine.getConfig().projects) {
@@ -1,7 +1,7 @@
1
1
  import{bm as i,bl as O,bo as e,bt as Ee,bE as ln,bA as ds,bF as cn,bG as dn,bH as un,c2 as Do,c3 as Lo,bD as To,bw as Mo,br as Ls,bs as Ts,bu as Ms,c4 as Is,c5 as Io,c6 as Ao,c7 as _o,c8 as zo,c9 as Fo,ca as hn,bM as mn,bJ as us,bK as Te,bB as pn,cb as ts,cc as Oo,cd as fn,ce as gn,bv as Uo,bx as Ho,by as ut,bz as Bo,bL as Wo,bI as Vo,cf as qo,cg as Go,bN as Ko}from"./DocContent-D5CLsUKq.js";var hs=/^(?:[a-z][a-z0-9+.-]*:|[\\/]{2})/i,xn=/^[\\/]{2}/;function Jo(t,s){return s+t.replace(/\\/g,"/")}var As="popstate";function _s(t){return typeof t=="object"&&t!=null&&"pathname"in t&&"search"in t&&"hash"in t&&"state"in t&&"key"in t}function Yo(t={}){function s(o,r){let{pathname:l="/",search:c="",hash:d=""}=ze(o.location.hash.substring(1));return!l.startsWith("/")&&!l.startsWith(".")&&(l="/"+l),ss("",{pathname:l,search:c,hash:d},r.state&&r.state.usr||null,r.state&&r.state.key||"default")}function n(o,r){let l=o.document.querySelector("base"),c="";if(l&&l.getAttribute("href")){let d=o.location.href,u=d.indexOf("#");c=u===-1?d:d.slice(0,u)}return c+"#"+(typeof r=="string"?r:Ae(r))}function a(o,r){ie(o.pathname.charAt(0)==="/",`relative pathnames are not supported in hash history.push(${JSON.stringify(r)})`)}return Qo(s,n,a,t)}function Z(t,s){if(t===!1||t===null||typeof t>"u")throw new Error(s)}function ie(t,s){if(!t){typeof console<"u"&&console.warn(s);try{throw new Error(s)}catch{}}}function Xo(){return Math.random().toString(36).substring(2,10)}function zs(t,s){return{usr:t.state,key:t.key,idx:s,masked:t.mask?{pathname:t.pathname,search:t.search,hash:t.hash}:void 0}}function ss(t,s,n=null,a,o){return{pathname:typeof t=="string"?t:t.pathname,search:"",hash:"",...typeof s=="string"?ze(s):s,state:n,key:s&&s.key||a||Xo(),mask:o}}function Ae({pathname:t="/",search:s="",hash:n=""}){return s&&s!=="?"&&(t+=s.charAt(0)==="?"?s:"?"+s),n&&n!=="#"&&(t+=n.charAt(0)==="#"?n:"#"+n),t}function ze(t){let s={};if(t){let n=t.indexOf("#");n>=0&&(s.hash=t.substring(n),t=t.substring(0,n));let a=t.indexOf("?");a>=0&&(s.search=t.substring(a),t=t.substring(0,a)),t&&(s.pathname=t)}return s}function Qo(t,s,n,a={}){let{window:o=document.defaultView,v5Compat:r=!1}=a,l=o.history,c="POP",d=null,u=m();u==null&&(u=0,l.replaceState({...l.state,idx:u},""));function m(){return(l.state||{idx:null}).idx}function h(){c="POP";let g=m(),y=g==null?null:g-u;u=g,d&&d({action:c,location:v.location,delta:y})}function p(g,y){c="PUSH";let N=_s(g)?g:ss(v.location,g,y);n&&n(N,g),u=m()+1;let j=zs(N,u),b=v.createHref(N.mask||N);try{l.pushState(j,"",b)}catch(E){if(E instanceof DOMException&&E.name==="DataCloneError")throw E;o.location.assign(b)}r&&d&&d({action:c,location:v.location,delta:1})}function f(g,y){c="REPLACE";let N=_s(g)?g:ss(v.location,g,y);n&&n(N,g),u=m();let j=zs(N,u),b=v.createHref(N.mask||N);l.replaceState(j,"",b),r&&d&&d({action:c,location:v.location,delta:0})}function k(g){return Zo(o,g)}let v={get action(){return c},get location(){return t(o,l)},listen(g){if(d)throw new Error("A history only accepts one active listener");return o.addEventListener(As,h),d=g,()=>{o.removeEventListener(As,h),d=null}},createHref(g){return s(o,g)},createURL:k,encodeLocation(g){let y=k(g);return{pathname:y.pathname,search:y.search,hash:y.hash}},push:p,replace:f,go(g){return l.go(g)}};return v}function Zo(t,s,n=!1){let a="http://localhost";t&&(a=t.location.origin!=="null"?t.location.origin:t.location.href),Z(a,"No window.location.(origin|href) available to create URL");let o=typeof s=="string"?s:Ae(s);return o=o.replace(/ $/,"%20"),!n&&xn.test(o)&&(o=a+o),new URL(o,a)}function vn(t,s,n="/"){return er(t,s,n,!1)}function er(t,s,n,a,o){let r=typeof s=="string"?ze(s):s,l=ve(r.pathname||"/",n);if(l==null)return null;let c=tr(t),d=null,u=hr(l);for(let m=0;d==null&&m<c.length;++m)d=ur(c[m],u,a);return d}function tr(t){let s=jn(t);return sr(s),s}function jn(t,s=[],n=[],a="",o=!1){let r=(l,c,d=o,u)=>{let m={relativePath:u===void 0?l.path||"":u,caseSensitive:l.caseSensitive===!0,childrenIndex:c,route:l};if(m.relativePath.startsWith("/")){if(!m.relativePath.startsWith(a)&&d)return;Z(m.relativePath.startsWith(a),`Absolute route path "${m.relativePath}" nested under path "${a}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),m.relativePath=m.relativePath.slice(a.length)}let h=le([a,m.relativePath]),p=n.concat(m);l.children&&l.children.length>0&&(Z(l.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${h}".`),jn(l.children,s,p,h,d)),!(l.path==null&&!l.index)&&s.push({path:h,score:cr(h,l.index),routesMeta:p.map((f,k)=>{let[v,g]=Nn(f.relativePath,f.caseSensitive,k===p.length-1);return{...f,matcher:v,compiledParams:g}})})};return t.forEach((l,c)=>{if(l.path===""||!l.path?.includes("?"))r(l,c);else for(let d of bn(l.path))r(l,c,!0,d)}),s}function bn(t){let s=t.split("/");if(s.length===0)return[];let[n,...a]=s,o=n.endsWith("?"),r=n.replace(/\?$/,"");if(a.length===0)return o?[r,""]:[r];let l=bn(a.join("/")),c=[];return c.push(...l.map(d=>d===""?r:[r,d].join("/"))),o&&c.push(...l),c.map(d=>t.startsWith("/")&&d===""?"/":d)}function sr(t){t.sort((s,n)=>s.score!==n.score?n.score-s.score:dr(s.routesMeta.map(a=>a.childrenIndex),n.routesMeta.map(a=>a.childrenIndex)))}var nr=/^:[\w-]+$/,ar=3,or=2,rr=1,lr=10,ir=-2,Fs=t=>t==="*";function cr(t,s){let n=t.split("/"),a=n.length;return n.some(Fs)&&(a+=ir),s&&(a+=or),n.filter(o=>!Fs(o)).reduce((o,r)=>o+(nr.test(r)?ar:r===""?rr:lr),a)}function dr(t,s){return t.length===s.length&&t.slice(0,-1).every((a,o)=>a===s[o])?t[t.length-1]-s[s.length-1]:0}function ur(t,s,n=!1){let{routesMeta:a}=t,o={},r="/",l=[];for(let c=0;c<a.length;++c){let d=a[c],u=c===a.length-1,m=r==="/"?s:s.slice(r.length)||"/",h={path:d.relativePath,caseSensitive:d.caseSensitive,end:u},p=d.matcher&&d.compiledParams?yn(h,m,d.matcher,d.compiledParams):Nt(h,m),f=d.route;if(!p&&u&&n&&!a[a.length-1].route.index&&(p=Nt({path:d.relativePath,caseSensitive:d.caseSensitive,end:!1},m)),!p)return null;Object.assign(o,p.params),l.push({params:o,pathname:le([r,p.pathname]),pathnameBase:fr(le([r,p.pathnameBase])),route:f}),p.pathnameBase!=="/"&&(r=le([r,p.pathnameBase]))}return l}function Nt(t,s){typeof t=="string"&&(t={path:t,caseSensitive:!1,end:!0});let[n,a]=Nn(t.path,t.caseSensitive,t.end);return yn(t,s,n,a)}function yn(t,s,n,a){let o=s.match(n);if(!o)return null;let r=o[0],l=_e(r,1),c=o.slice(1);return{params:a.reduce((u,{paramName:m,isOptional:h},p)=>{if(m==="*"){let k=c[p]||"";l=_e(r.slice(0,r.length-k.length),1)}const f=c[p];return h&&!f?u[m]=void 0:u[m]=(f||"").replace(/%2F/g,"/"),u},{}),pathname:r,pathnameBase:l,pattern:t}}function Nn(t,s=!1,n=!0){ie(t==="*"||!t.endsWith("*")||t.endsWith("/*"),`Route path "${t}" will be treated as if it were "${t.replace(/\*$/,"/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${t.replace(/\*$/,"/*")}".`);let a=[],o="^"+t.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(l,c,d,u,m)=>{if(a.push({paramName:c,isOptional:d!=null}),d){let h=m.charAt(u+l.length);return h&&h!=="/"?"/([^\\/]*)":"(?:/([^\\/]*))?"}return"/([^\\/]+)"}).replace(/\/([\w-]+)\?(\/|$)/g,"(/$1)?$2");return t.endsWith("*")?(a.push({paramName:"*"}),o+=t==="*"||t==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):n?o+="\\/*$":t!==""&&t!=="/"&&(o+="(?:(?=\\/|$))"),[new RegExp(o,s?void 0:"i"),a]}function hr(t){try{return t.split("/").map(s=>decodeURIComponent(s).replace(/\//g,"%2F")).join("/")}catch(s){return ie(!1,`The URL path "${t}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${s}).`),t}}function ve(t,s){if(s==="/")return t;if(!t.toLowerCase().startsWith(s.toLowerCase()))return null;let n=s.endsWith("/")?s.length-1:s.length,a=t.charAt(n);return a&&a!=="/"?null:t.slice(n)||"/"}function mr(t,s="/"){let{pathname:n,search:a="",hash:o=""}=typeof t=="string"?ze(t):t,r;return n?(n=Cn(n),n.startsWith("/")||n.startsWith("\\")?r=Os(n.substring(1),"/"):r=Os(n,s)):r=s,{pathname:r,search:gr(a),hash:xr(o)}}function Os(t,s){let n=_e(s).split("/");return t.split("/").forEach(o=>{o===".."?n.length>1&&n.pop():o!=="."&&n.push(o)}),n.length>1?n.join("/"):"/"}function Vt(t,s,n,a){return`Cannot include a '${t}' character in a manually specified \`to.${s}\` field [${JSON.stringify(a)}]. Please separate it out to the \`to.${n}\` field. Alternatively you may provide the full path as a string in <Link to="..."> and the router will parse it for you.`}function pr(t){return t.filter((s,n)=>n===0||s.route.path&&s.route.path.length>0)}function wn(t){let s=pr(t);return s.map((n,a)=>a===s.length-1?n.pathname:n.pathnameBase)}function ms(t,s,n,a=!1){let o;typeof t=="string"?o=ze(t):(o={...t},Z(!o.pathname||!o.pathname.includes("?"),Vt("?","pathname","search",o)),Z(!o.pathname||!o.pathname.includes("#"),Vt("#","pathname","hash",o)),Z(!o.search||!o.search.includes("#"),Vt("#","search","hash",o)));let r=t===""||o.pathname==="",l=r?"/":o.pathname,c;if(l==null)c=n;else{let h=s.length-1;if(!a&&l.startsWith("..")){let p=l.split("/");for(;p[0]==="..";)p.shift(),h-=1;o.pathname=p.join("/")}c=h>=0?s[h]:"/"}let d=mr(o,c),u=l&&l!=="/"&&l.endsWith("/"),m=(r||l===".")&&n.endsWith("/");return!d.pathname.endsWith("/")&&(u||m)&&(d.pathname+="/"),d}var Cn=t=>t.replace(/[\\/]{2,}/g,"/"),le=t=>Cn(t.join("/"));function _e(t,s=0){let n=t.length;for(;n>s&&t.charCodeAt(n-1)===47;)n--;return n===t.length?t:t.slice(0,n)}var fr=t=>_e(t).replace(/^\/*/,"/"),gr=t=>!t||t==="?"?"":t.startsWith("?")?t:"?"+t,xr=t=>!t||t==="#"?"":t.startsWith("#")?t:"#"+t,vr=class{constructor(t,s,n,a=!1){this.status=t,this.statusText=s||"",this.internal=a,n instanceof Error?(this.data=n.toString(),this.error=n):this.data=n}};function jr(t){return t!=null&&typeof t.status=="number"&&typeof t.statusText=="string"&&typeof t.internal=="boolean"&&"data"in t}function br(t){let s=t.map(n=>n.route.path).filter(Boolean);return le(s)||"/"}var kn=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function Sn(t,s){let n=t;if(typeof n!="string"||!hs.test(n))return{absoluteURL:void 0,isExternal:!1,to:n};let a=n,o=!1;if(kn)try{let r=new URL(window.location.href),l=xn.test(n)?new URL(Jo(n,r.protocol)):new URL(n),c=ve(l.pathname,s);l.origin===r.origin&&c!=null?n=c+l.search+l.hash:o=!0}catch{ie(!1,`<Link to="${n}"> contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}return{absoluteURL:a,isExternal:o,to:n}}Object.getOwnPropertyNames(Object.prototype).sort().join("\0");var Us=new URL("http://localhost");function En(t){if(t.createURL)return t.createURL("/");try{return new URL(t.createHref("/"),Us)}catch{return Us}}function qt(t,s){return t.origin===s.origin&&(t.origin!=="null"||t.protocol===s.protocol&&t.host===s.host)}function yr(t,s){if(t.startsWith("//"))return!0;let n=s.protocol.toLowerCase();return t.toLowerCase().startsWith(n)?s.host===""||t.slice(n.length).startsWith("//"):!1}function $n(t,s,n,a){let o=null;try{o=t==null?null:new URL(t,n)}catch{}let r=new URL(s,n),l=o!=null&&!qt(o,n),c=!qt(r,n);if(a==="reject"){if(l||c)throw new Error("External navigation is not allowed")}else if(c&&(o==null||!yr(t,o)||!qt(o,r)))throw new Error("External navigation is not allowed")}var Rn=["POST","PUT","PATCH","DELETE"];new Set(Rn);var Nr=["GET",...Rn];new Set(Nr);var wr=["about:","blob:","chrome:","chrome-untrusted:","content:","data:","devtools:","file:","filesystem:","javascript:"];function Cr(t){try{return wr.includes(new URL(t).protocol)}catch{return!1}}var Fe=i.createContext(null);Fe.displayName="DataRouter";var Et=i.createContext(null);Et.displayName="DataRouterState";var Pn=i.createContext(!1);function kr(){return i.useContext(Pn)}var Dn=i.createContext({isTransitioning:!1});Dn.displayName="ViewTransition";var Sr=i.createContext(new Map);Sr.displayName="Fetchers";var Er=i.createContext(null);Er.displayName="Await";var oe=i.createContext(null);oe.displayName="Navigation";var $t=i.createContext(null);$t.displayName="Location";var je=i.createContext({outlet:null,matches:[],isDataRoute:!1});je.displayName="Route";var ps=i.createContext(null);ps.displayName="RouteError";var Ln="REACT_ROUTER_ERROR",$r="REDIRECT",Rr="ROUTE_ERROR_RESPONSE";function Pr(t){if(t.startsWith(`${Ln}:${$r}:{`))try{let s=JSON.parse(t.slice(28));if(typeof s=="object"&&s&&typeof s.status=="number"&&typeof s.statusText=="string"&&typeof s.location=="string"&&typeof s.reloadDocument=="boolean"&&typeof s.replace=="boolean")return s}catch{}}function Dr(t){if(t.startsWith(`${Ln}:${Rr}:{`))try{let s=JSON.parse(t.slice(40));if(typeof s=="object"&&s&&typeof s.status=="number"&&typeof s.statusText=="string")return new vr(s.status,s.statusText,s.data)}catch{}}function Lr(t,{relative:s}={}){Z(st(),"useHref() may be used only in the context of a <Router> component.");let{basename:n,navigator:a}=i.useContext(oe),{hash:o,pathname:r,search:l}=nt(t,{relative:s}),c=r;return n!=="/"&&(c=r==="/"?n:le([n,r])),a.createHref({pathname:c,search:l,hash:o})}function st(){return i.useContext($t)!=null}function ce(){return Z(st(),"useLocation() may be used only in the context of a <Router> component."),i.useContext($t).location}var Tn="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function Mn(t){i.useContext(oe).static||i.useLayoutEffect(t)}function re(){let{isDataRoute:t}=i.useContext(je);return t?Vr():Tr()}function Tr(){Z(st(),"useNavigate() may be used only in the context of a <Router> component.");let t=i.useContext(Fe),{basename:s,navigator:n}=i.useContext(oe),{matches:a}=i.useContext(je),{pathname:o}=ce(),r=JSON.stringify(wn(a)),l=i.useRef(!1);return Mn(()=>{l.current=!0}),i.useCallback((d,u={})=>{if(ie(l.current,Tn),!l.current)return;if(typeof d=="number"){n.go(d);return}let m=ms(d,JSON.parse(r),o,u.relative==="path");t==null&&s!=="/"&&(m.pathname=m.pathname==="/"?s:le([s,m.pathname])),$n(typeof d=="string"?d:Ae(d),n.createHref(m),En(n),"reject"),(u.replace?n.replace:n.push)(m,u.state,u)},[s,n,r,o,t])}i.createContext(null);function nt(t,{relative:s}={}){let{matches:n}=i.useContext(je),{pathname:a}=ce(),o=JSON.stringify(wn(n));return i.useMemo(()=>ms(t,JSON.parse(o),a,s==="path"),[t,o,a,s])}function Mr(t,s){return In(t)}function In(t,s,n){Z(st(),"useRoutes() may be used only in the context of a <Router> component.");let{navigator:a}=i.useContext(oe),{matches:o}=i.useContext(je),r=o[o.length-1],l=r?r.params:{},c=r?r.pathname:"/",d=r?r.pathnameBase:"/",u=r&&r.route;{let g=u&&u.path||"";_n(c,!u||g.endsWith("*")||g.endsWith("*?"),`You rendered descendant <Routes> (or called \`useRoutes()\`) at "${c}" (under <Route path="${g}">) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render.
2
2
 
3
3
  Please change the parent <Route path="${g}"> to <Route path="${g==="/"?"*":`${g}/*`}">.`)}let m=ce(),h;h=m;let p=h.pathname||"/",f=p;if(d!=="/"){let g=d.replace(/^\//,"").split("/");f="/"+p.replace(/^\//,"").split("/").slice(g.length).join("/")}let k=n&&n.state.matches.length?n.state.matches.map(g=>Object.assign(g,{route:n.manifest[g.route.id]||g.route})):vn(t,{pathname:f});return ie(u||k!=null,`No routes matched location "${h.pathname}${h.search}${h.hash}" `),ie(k==null||k[k.length-1].route.element!==void 0||k[k.length-1].route.Component!==void 0||k[k.length-1].route.lazy!==void 0,`Matched leaf route at location "${h.pathname}${h.search}${h.hash}" does not have an element or Component. This means it will render an <Outlet /> with a null value by default resulting in an "empty" page.`),Fr(k&&k.map(g=>Object.assign({},g,{params:Object.assign({},l,g.params),pathname:le([d,a.encodeLocation?a.encodeLocation(g.pathname.replace(/%/g,"%25").replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:g.pathname]),pathnameBase:g.pathnameBase==="/"?d:le([d,a.encodeLocation?a.encodeLocation(g.pathnameBase.replace(/%/g,"%25").replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:g.pathnameBase])})),o,n)}function Ir(){let t=Wr(),s=jr(t)?`${t.status} ${t.statusText}`:t instanceof Error?t.message:JSON.stringify(t),n=t instanceof Error?t.stack:null,a="rgba(200,200,200, 0.5)",o={padding:"0.5rem",backgroundColor:a},r={padding:"2px 4px",backgroundColor:a},l=null;return console.error("Error handled by React Router default ErrorBoundary:",t),l=i.createElement(i.Fragment,null,i.createElement("p",null,"💿 Hey developer 👋"),i.createElement("p",null,"You can provide a way better UX than this when your app throws errors by providing your own ",i.createElement("code",{style:r},"ErrorBoundary")," or"," ",i.createElement("code",{style:r},"errorElement")," prop on your route.")),i.createElement(i.Fragment,null,i.createElement("h2",null,"Unexpected Application Error!"),i.createElement("h3",{style:{fontStyle:"italic"}},s),n?i.createElement("pre",{style:o},n):null,l)}var Ar=i.createElement(Ir,null),An=class extends i.Component{constructor(t){super(t),this.state={location:t.location,revalidation:t.revalidation,error:t.error}}static getDerivedStateFromError(t){return{error:t}}static getDerivedStateFromProps(t,s){return s.location!==t.location||s.revalidation!=="idle"&&t.revalidation==="idle"?{error:t.error,location:t.location,revalidation:t.revalidation}:{error:t.error!==void 0?t.error:s.error,location:s.location,revalidation:t.revalidation||s.revalidation}}componentDidCatch(t,s){this.props.onError?this.props.onError(t,s):console.error("React Router caught the following error during render",t)}render(){let t=this.state.error;if(this.context&&typeof t=="object"&&t&&"digest"in t&&typeof t.digest=="string"){const n=Dr(t.digest);n&&(t=n)}let s=t!==void 0?i.createElement(je.Provider,{value:this.props.routeContext},i.createElement(ps.Provider,{value:t,children:this.props.component})):this.props.children;return this.context?i.createElement(_r,{error:t},s):s}};An.contextType=Pn;var Gt=new WeakMap;function _r({children:t,error:s}){let{basename:n,navigator:a}=i.useContext(oe);if(typeof s=="object"&&s&&"digest"in s&&typeof s.digest=="string"){let o=Pr(s.digest);if(o){let r=Gt.get(s);if(r)throw r;let l=Sn(o.location,n),c=l.absoluteURL||l.to;if($n(o.location,c,En(a),"allow-explicit"),Cr(c))throw new Error("Invalid redirect location");if(kn&&!Gt.get(s))if(l.isExternal||o.reloadDocument)window.location.href=c;else{const d=Promise.resolve().then(()=>window.__reactRouterDataRouter.navigate(l.to,{replace:o.replace}));throw Gt.set(s,d),d}return i.createElement("meta",{httpEquiv:"refresh",content:`0;url=${c}`})}}return t}function zr({routeContext:t,match:s,children:n}){let a=i.useContext(Fe);return a&&a.static&&a.staticContext&&(s.route.errorElement||s.route.ErrorBoundary)&&(a.staticContext._deepestRenderedBoundaryId=s.route.id),i.createElement(je.Provider,{value:t},n)}function Fr(t,s=[],n){let a=n?.state;if(t==null){if(!a)return null;if(a.errors)t=a.matches;else if(s.length===0&&!a.initialized&&a.matches.length>0)t=a.matches;else return null}let o=t,r=a?.errors;if(r!=null){let m=o.findIndex(h=>h.route.id&&r?.[h.route.id]!==void 0);Z(m>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(r).join(",")}`),o=o.slice(0,Math.min(o.length,m+1))}let l=!1,c=-1;if(n&&a){l=a.renderFallback;for(let m=0;m<o.length;m++){let h=o[m];if((h.route.HydrateFallback||h.route.hydrateFallbackElement)&&(c=m),h.route.id){let{loaderData:p,errors:f}=a,k=h.route.loader&&!p.hasOwnProperty(h.route.id)&&(!f||f[h.route.id]===void 0);if(h.route.lazy||k){n.isStatic&&(l=!0),c>=0?o=o.slice(0,c+1):o=[o[0]];break}}}}let d=n?.onError,u=a&&d?(m,h)=>{d(m,{location:a.location,params:a.matches?.[0]?.params??{},pattern:br(a.matches),errorInfo:h})}:void 0;return o.reduceRight((m,h,p)=>{let f,k=!1,v=null,g=null;a&&(f=r&&h.route.id?r[h.route.id]:void 0,v=h.route.errorElement||Ar,l&&(c<0&&p===0?(_n("route-fallback",!1,"No `HydrateFallback` element provided to render during initial hydration"),k=!0,g=null):c===p&&(k=!0,g=h.route.hydrateFallbackElement||null)));let y=s.concat(o.slice(0,p+1)),N=()=>{let j;return f?j=v:k?j=g:h.route.Component?j=i.createElement(h.route.Component,null):h.route.element?j=h.route.element:j=m,i.createElement(zr,{match:h,routeContext:{outlet:m,matches:y,isDataRoute:a!=null},children:j})};return a&&(h.route.ErrorBoundary||h.route.errorElement||p===0)?i.createElement(An,{location:a.location,revalidation:a.revalidation,component:v,error:f,children:N(),routeContext:{outlet:null,matches:y,isDataRoute:!0},onError:u}):N()},null)}function fs(t){return`${t} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function Or(t){let s=i.useContext(Fe);return Z(s,fs(t)),s}function Ur(t){let s=i.useContext(Et);return Z(s,fs(t)),s}function Hr(t){let s=i.useContext(je);return Z(s,fs(t)),s}function gs(t){let s=Hr(t),n=s.matches[s.matches.length-1];return Z(n.route.id,`${t} can only be used on routes that contain a unique "id"`),n.route.id}function Br(){return gs("useRouteId")}function Wr(){let t=i.useContext(ps),s=Ur("useRouteError"),n=gs("useRouteError");return t!==void 0?t:s.errors?.[n]}function Vr(){let{router:t}=Or("useNavigate"),s=gs("useNavigate"),n=i.useRef(!1);return Mn(()=>{n.current=!0}),i.useCallback(async(o,r={})=>{ie(n.current,Tn),n.current&&(typeof o=="number"?await t.navigate(o):await t.navigate(o,{fromRouteId:s,...r}))},[t,s])}var Hs={};function _n(t,s,n){!s&&!Hs[t]&&(Hs[t]=!0,ie(!1,n))}i.memo(qr);function qr({routes:t,manifest:s,future:n,state:a,isStatic:o,onError:r}){return In(t,void 0,{manifest:s,state:a,isStatic:o,onError:r})}function Gr({basename:t="/",children:s=null,location:n,navigationType:a="POP",navigator:o,static:r=!1,useTransitions:l}){Z(!st(),"You cannot render a <Router> inside another <Router>. You should never have more than one in your app.");let c=t.replace(/^\/*/,"/"),d=i.useMemo(()=>({basename:c,navigator:o,static:r,useTransitions:l,future:{}}),[c,o,r,l]);typeof n=="string"&&(n=ze(n));let{pathname:u="/",search:m="",hash:h="",state:p=null,key:f="default",mask:k}=n,v=i.useMemo(()=>{let g=ve(u,c);return g==null?null:{location:{pathname:g,search:m,hash:h,state:p,key:f,mask:k},navigationType:a}},[c,u,m,h,p,f,a,k]);return ie(v!=null,`<Router basename="${c}"> is not able to match the URL "${u}${m}${h}" because it does not start with the basename, so the <Router> won't render anything.`),v==null?null:i.createElement(oe.Provider,{value:d},i.createElement($t.Provider,{children:s,value:v}))}var xt="get",vt="application/x-www-form-urlencoded";function Rt(t){return typeof HTMLElement<"u"&&t instanceof HTMLElement}function Kr(t){return Rt(t)&&t.tagName.toLowerCase()==="button"}function Jr(t){return Rt(t)&&t.tagName.toLowerCase()==="form"}function Yr(t){return Rt(t)&&t.tagName.toLowerCase()==="input"}function Xr(t){return!!(t.metaKey||t.altKey||t.ctrlKey||t.shiftKey)}function Qr(t,s){return t.button===0&&(!s||s==="_self")&&!Xr(t)}var ht=null;function Zr(){if(ht===null)try{new FormData(document.createElement("form"),0),ht=!1}catch{ht=!0}return ht}var el=new Set(["application/x-www-form-urlencoded","multipart/form-data","text/plain"]);function Kt(t){return t!=null&&!el.has(t)?(ie(!1,`"${t}" is not a valid \`encType\` for \`<Form>\`/\`<fetcher.Form>\` and will default to "${vt}"`),null):t}function tl(t,s){let n,a,o,r,l;if(Jr(t)){let c=t.getAttribute("action");a=c?ve(c,s):null,n=t.getAttribute("method")||xt,o=Kt(t.getAttribute("enctype"))||vt,r=new FormData(t)}else if(Kr(t)||Yr(t)&&(t.type==="submit"||t.type==="image")){let c=t.form;if(c==null)throw new Error('Cannot submit a <button> or <input type="submit"> without a <form>');let d=t.getAttribute("formaction")||c.getAttribute("action");if(a=d?ve(d,s):null,n=t.getAttribute("formmethod")||c.getAttribute("method")||xt,o=Kt(t.getAttribute("formenctype"))||Kt(c.getAttribute("enctype"))||vt,r=new FormData(c,t),!Zr()){let{name:u,type:m,value:h}=t;if(m==="image"){let p=u?`${u}.`:"";r.append(`${p}x`,"0"),r.append(`${p}y`,"0")}else u&&r.append(u,h)}}else{if(Rt(t))throw new Error('Cannot submit element that is not <form>, <button>, or <input type="submit|image">');n=xt,a=null,o=vt,l=t}return r&&o==="text/plain"&&(l=r,r=void 0),{action:a,method:n.toLowerCase(),encType:o,formData:r,body:l}}Object.getOwnPropertyNames(Object.prototype).sort().join("\0");function xs(t,s){if(t===!1||t===null||typeof t>"u")throw new Error(s)}function zn(t,s,n,a){let o=typeof t=="string"?new URL(t,typeof window>"u"?"server://singlefetch/":window.location.origin):t;return n?o.pathname.endsWith("/")?o.pathname=`${o.pathname}_.${a}`:o.pathname=`${o.pathname}.${a}`:o.pathname==="/"?o.pathname=`_root.${a}`:s&&ve(o.pathname,s)==="/"?o.pathname=`${_e(s)}/_root.${a}`:o.pathname=`${_e(o.pathname)}.${a}`,o}async function sl(t,s){if(t.id in s)return s[t.id];try{let n=await import(t.module);return s[t.id]=n,n}catch(n){return console.error(`Error loading route module \`${t.module}\`, reloading page...`),console.error(n),window.__reactRouterContext&&window.__reactRouterContext.isSpaMode,window.location.reload(),new Promise(()=>{})}}function nl(t){return t==null?!1:t.href==null?t.rel==="preload"&&typeof t.imageSrcSet=="string"&&typeof t.imageSizes=="string":typeof t.rel=="string"&&typeof t.href=="string"}async function al(t,s,n){let a=await Promise.all(t.map(async o=>{let r=s.routes[o.route.id];if(r){let l=await sl(r,n);return l.links?l.links():[]}return[]}));return il(a.flat(1).filter(nl).filter(o=>o.rel==="stylesheet"||o.rel==="preload").map(o=>o.rel==="stylesheet"?{...o,rel:"prefetch",as:"style"}:{...o,rel:"prefetch"}))}function Bs(t,s,n,a,o,r){let l=(d,u)=>n[u]?d.route.id!==n[u].route.id:!0,c=(d,u)=>n[u].pathname!==d.pathname||n[u].route.path?.endsWith("*")&&n[u].params["*"]!==d.params["*"];return r==="assets"?s.filter((d,u)=>l(d,u)||c(d,u)):r==="data"?s.filter((d,u)=>{let m=a.routes[d.route.id];if(!m||!m.hasLoader)return!1;if(l(d,u)||c(d,u))return!0;if(d.route.shouldRevalidate){let h=d.route.shouldRevalidate({currentUrl:new URL(o.pathname+o.search+o.hash,window.origin),currentParams:n[0]?.params||{},nextUrl:new URL(t,window.origin),nextParams:d.params,defaultShouldRevalidate:!0});if(typeof h=="boolean")return h}return!0}):[]}function ol(t,s,{includeHydrateFallback:n}={}){return rl(t.map(a=>{let o=s.routes[a.route.id];if(!o)return[];let r=[o.module];return o.clientActionModule&&(r=r.concat(o.clientActionModule)),o.clientLoaderModule&&(r=r.concat(o.clientLoaderModule)),n&&o.hydrateFallbackModule&&(r=r.concat(o.hydrateFallbackModule)),o.imports&&(r=r.concat(o.imports)),r}).flat(1))}function rl(t){return[...new Set(t)]}function ll(t){let s={},n=Object.keys(t).sort();for(let a of n)s[a]=t[a];return s}function il(t,s){let n=new Set;return new Set(s),t.reduce((a,o)=>{let r=JSON.stringify(ll(o));return n.has(r)||(n.add(r),a.push({key:r,link:o})),a},[])}function vs(){let t=i.useContext(Fe);return xs(t,"You must render this element inside a <DataRouterContext.Provider> element"),t}function cl(){let t=i.useContext(Et);return xs(t,"You must render this element inside a <DataRouterStateContext.Provider> element"),t}var js=i.createContext(void 0);js.displayName="FrameworkContext";function Pt(){let t=i.useContext(js);return xs(t,"You must render this element inside a <HydratedRouter> element"),t}function dl(t,s){let n=i.useContext(js),[a,o]=i.useState(!1),[r,l]=i.useState(!1),{onFocus:c,onBlur:d,onMouseEnter:u,onMouseLeave:m,onTouchStart:h}=s,p=i.useRef(null);i.useEffect(()=>{if(t==="render"&&l(!0),t==="viewport"){let v=y=>{y.forEach(N=>{l(N.isIntersecting)})},g=new IntersectionObserver(v,{threshold:.5});return p.current&&g.observe(p.current),()=>{g.disconnect()}}},[t]),i.useEffect(()=>{if(a){let v=setTimeout(()=>{l(!0)},100);return()=>{clearTimeout(v)}}},[a]);let f=()=>{o(!0)},k=()=>{o(!1),l(!1)};return n?t!=="intent"?[r,p,{}]:[r,p,{onFocus:Je(c,f),onBlur:Je(d,k),onMouseEnter:Je(u,f),onMouseLeave:Je(m,k),onTouchStart:Je(h,f)}]:[!1,p,{}]}function Je(t,s){return n=>{t&&t(n),n.defaultPrevented||s(n)}}function ul({page:t,...s}){let n=kr(),{nonce:a}=Pt(),{router:o}=vs(),r=i.useMemo(()=>vn(o.routes,t,o.basename),[o.routes,t,o.basename]);return r?(s.nonce==null&&a&&(s={...s,nonce:a}),n?i.createElement(ml,{page:t,matches:r,...s}):i.createElement(pl,{page:t,matches:r,...s})):null}function hl(t){let{manifest:s,routeModules:n}=Pt(),[a,o]=i.useState([]);return i.useEffect(()=>{let r=!1;return al(t,s,n).then(l=>{r||o(l)}),()=>{r=!0}},[t,s,n]),a}function ml({page:t,matches:s,...n}){let a=ce(),{future:o}=Pt(),{basename:r}=vs(),l=i.useMemo(()=>{if(t===a.pathname+a.search+a.hash)return[];let c=zn(t,r,o.v8_trailingSlashAwareDataRequests,"rsc"),d=!1,u=[];for(let m of s)typeof m.route.shouldRevalidate=="function"?d=!0:u.push(m.route.id);return d&&u.length>0&&c.searchParams.set("_routes",u.join(",")),[c.pathname+c.search]},[r,o.v8_trailingSlashAwareDataRequests,t,a,s]);return i.createElement(i.Fragment,null,l.map(c=>i.createElement("link",{key:c,rel:"prefetch",as:"fetch",href:c,...n})))}function pl({page:t,matches:s,...n}){let a=ce(),{future:o,manifest:r,routeModules:l}=Pt(),{basename:c}=vs(),{loaderData:d,matches:u}=cl(),m=i.useMemo(()=>Bs(t,s,u,r,a,"data"),[t,s,u,r,a]),h=i.useMemo(()=>Bs(t,s,u,r,a,"assets"),[t,s,u,r,a]),p=i.useMemo(()=>{if(t===a.pathname+a.search+a.hash)return[];let v=new Set,g=!1;if(s.forEach(N=>{let j=r.routes[N.route.id];!j||!j.hasLoader||(!m.some(b=>b.route.id===N.route.id)&&N.route.id in d&&l[N.route.id]?.shouldRevalidate||j.hasClientLoader?g=!0:v.add(N.route.id))}),v.size===0)return[];let y=zn(t,c,o.v8_trailingSlashAwareDataRequests,"data");return g&&v.size>0&&y.searchParams.set("_routes",s.filter(N=>v.has(N.route.id)).map(N=>N.route.id).join(",")),[y.pathname+y.search]},[c,o.v8_trailingSlashAwareDataRequests,d,a,r,m,s,t,l]),f=i.useMemo(()=>ol(h,r),[h,r]),k=hl(h);return i.createElement(i.Fragment,null,p.map(v=>i.createElement("link",{key:v,rel:"prefetch",as:"fetch",href:v,...n})),f.map(v=>i.createElement("link",{key:v,rel:"modulepreload",href:v,...n})),k.map(({key:v,link:g})=>i.createElement("link",{key:v,nonce:n.nonce,...g,crossOrigin:g.crossOrigin??n.crossOrigin})))}function fl(...t){return s=>{t.forEach(n=>{typeof n=="function"?n(s):n!=null&&(n.current=s)})}}var gl=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";try{gl&&(window.__reactRouterVersion="7.18.4")}catch{}function xl({basename:t,children:s,useTransitions:n,window:a}){let o=i.useRef();o.current==null&&(o.current=Yo({window:a,v5Compat:!0}));let r=o.current,[l,c]=i.useState({action:r.action,location:r.location}),d=i.useCallback(u=>{n===!1?c(u):i.startTransition(()=>c(u))},[n]);return i.useLayoutEffect(()=>r.listen(d),[r,d]),i.createElement(Gr,{basename:t,children:s,location:l.location,navigationType:l.action,navigator:r,useTransitions:n})}var Fn=i.forwardRef(function({onClick:s,discover:n="render",prefetch:a="none",relative:o,reloadDocument:r,replace:l,mask:c,state:d,target:u,to:m,preventScrollReset:h,viewTransition:p,defaultShouldRevalidate:f,...k},v){let{basename:g,navigator:y,useTransitions:N}=i.useContext(oe),j=typeof m=="string"&&hs.test(m),b=Sn(m,g);m=b.to;let E=Lr(m,{relative:o}),D=ce(),$=null;if(c){let W=ms(c,[],D.mask?D.mask.pathname:"/",!0);g!=="/"&&(W.pathname=W.pathname==="/"?g:le([g,W.pathname])),$=y.createHref(W)}let[w,S,I]=dl(a,k),x=yl(m,{replace:l,mask:c,state:d,target:u,preventScrollReset:h,relative:o,viewTransition:p,defaultShouldRevalidate:f,useTransitions:N});function P(W){s&&s(W),W.defaultPrevented||x(W)}let F=!(b.isExternal||r),B=i.createElement("a",{...k,...I,href:(F?$:void 0)||b.absoluteURL||E,onClick:F?P:s,ref:fl(v,S),target:u,"data-discover":!j&&n==="render"?"true":void 0});return w&&!j?i.createElement(i.Fragment,null,B,i.createElement(ul,{page:E})):B});Fn.displayName="Link";var vl=i.forwardRef(function({"aria-current":s="page",caseSensitive:n=!1,className:a="",end:o=!1,style:r,to:l,viewTransition:c,children:d,...u},m){let h=nt(l,{relative:u.relative}),p=ce(),f=i.useContext(Et),{navigator:k,basename:v}=i.useContext(oe),g=f!=null&&Sl(h)&&c===!0,y=k.encodeLocation?k.encodeLocation(h).pathname:h.pathname,N=p.pathname,j=f&&f.navigation&&f.navigation.location?f.navigation.location.pathname:null;n||(N=N.toLowerCase(),j=j?j.toLowerCase():null,y=y.toLowerCase()),j&&v&&(j=ve(j,v)||j);const b=y!=="/"&&y.endsWith("/")?y.length-1:y.length;let E=N===y||!o&&N.startsWith(y)&&N.charAt(b)==="/",D=j!=null&&(j===y||!o&&j.startsWith(y)&&j.charAt(y.length)==="/"),$={isActive:E,isPending:D,isTransitioning:g},w=E?s:void 0,S;typeof a=="function"?S=a($):S=[a,E?"active":null,D?"pending":null,g?"transitioning":null].filter(Boolean).join(" ");let I=typeof r=="function"?r($):r;return i.createElement(Fn,{...u,"aria-current":w,className:S,ref:m,style:I,to:l,viewTransition:c},typeof d=="function"?d($):d)});vl.displayName="NavLink";var jl=i.forwardRef(({discover:t="render",fetcherKey:s,navigate:n,reloadDocument:a,replace:o,state:r,method:l=xt,action:c,onSubmit:d,relative:u,preventScrollReset:m,viewTransition:h,defaultShouldRevalidate:p,...f},k)=>{let{useTransitions:v}=i.useContext(oe),g=Cl(),y=kl(c,{relative:u}),N=l.toLowerCase()==="get"?"get":"post",j=typeof c=="string"&&hs.test(c),b=E=>{if(d&&d(E),E.defaultPrevented)return;E.preventDefault();let D=E.nativeEvent.submitter,$=D?.getAttribute("formmethod")||l,w=()=>g(D||E.currentTarget,{fetcherKey:s,method:$,navigate:n,replace:o,state:r,relative:u,preventScrollReset:m,viewTransition:h,defaultShouldRevalidate:p});v&&n!==!1?i.startTransition(()=>w()):w()};return i.createElement("form",{ref:k,method:N,action:y,onSubmit:a?d:b,...f,"data-discover":!j&&t==="render"?"true":void 0})});jl.displayName="Form";function bl(t){return`${t} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function On(t){let s=i.useContext(Fe);return Z(s,bl(t)),s}function yl(t,{target:s,replace:n,mask:a,state:o,preventScrollReset:r,relative:l,viewTransition:c,defaultShouldRevalidate:d,useTransitions:u}={}){let m=re(),h=ce(),p=nt(t,{relative:l});return i.useCallback(f=>{if(Qr(f,s)){f.preventDefault();let k=n!==void 0?n:Ae(h)===Ae(p),v=()=>m(t,{replace:k,mask:a,state:o,preventScrollReset:r,relative:l,viewTransition:c,defaultShouldRevalidate:d});u?i.startTransition(()=>v()):v()}},[h,m,p,n,a,o,s,t,r,l,c,d,u])}var Nl=0,wl=()=>`__${String(++Nl)}__`;function Cl(){let{router:t}=On("useSubmit"),{basename:s}=i.useContext(oe),n=Br(),a=t.fetch,o=t.navigate;return i.useCallback(async(r,l={})=>{let{action:c,method:d,encType:u,formData:m,body:h}=tl(r,s);if(l.navigate===!1){let p=l.fetcherKey||wl();await a(p,n,l.action||c,{defaultShouldRevalidate:l.defaultShouldRevalidate,preventScrollReset:l.preventScrollReset,formData:m,body:h,formMethod:l.method||d,formEncType:l.encType||u,flushSync:l.flushSync})}else await o(l.action||c,{defaultShouldRevalidate:l.defaultShouldRevalidate,preventScrollReset:l.preventScrollReset,formData:m,body:h,formMethod:l.method||d,formEncType:l.encType||u,replace:l.replace,state:l.state,fromRouteId:n,flushSync:l.flushSync,viewTransition:l.viewTransition})},[a,o,s,n])}function kl(t,{relative:s}={}){let{basename:n}=i.useContext(oe),a=i.useContext(je);Z(a,"useFormAction must be used inside a RouteContext");let[o]=a.matches.slice(-1),r={...nt(t||".",{relative:s})},l=ce();if(t==null){r.search=l.search;let c=new URLSearchParams(r.search),d=c.getAll("index");if(d.some(m=>m==="")){c.delete("index"),d.filter(h=>h).forEach(h=>c.append("index",h));let m=c.toString();r.search=m?`?${m}`:""}}return(!t||t===".")&&o.route.index&&(r.search=r.search?r.search.replace(/^\?/,"?index&"):"?index"),n!=="/"&&(r.pathname=r.pathname==="/"?n:le([n,r.pathname])),Ae(r)}function Sl(t,{relative:s}={}){let n=i.useContext(Dn);Z(n!=null,"`useViewTransitionState` must be used within `react-router-dom`'s `RouterProvider`. Did you accidentally import `RouterProvider` from `react-router`?");let{basename:a}=On("useViewTransitionState"),o=nt(t,{relative:s});if(!n.isTransitioning)return!1;let r=ve(n.currentLocation.pathname,a)||n.currentLocation.pathname,l=ve(n.nextLocation.pathname,a)||n.nextLocation.pathname;return Nt(o.pathname,l)!=null||Nt(o.pathname,r)!=null}const Un={name:"book-open",size:24,node:[["path",{d:"M12 5v16",key:"1f6ucr"}],["path",{d:"M20.001 19A2 2 0 0022 17V5a2 2 0 00-1.999-2L16 3.002A5 5 0 0012 5a5 5 0 00-4-2H4a2 2 0 00-2 2v12a2 2 0 001.999 2H8a5 5 0 014 2 5 5 0 014-2z",key:"1fyvmf"}]]};Un.node;const El=O(Un);const Hn={name:"chevron-down",size:24,node:[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]]};Hn.node;const Dt=O(Hn);const Bn={name:"chevron-right",size:24,node:[["path",{d:"m9 18 6-6-6-6",key:"mthhwq"}]]};Bn.node;const $l=O(Bn);const Wn={name:"chevron-up",size:24,node:[["path",{d:"m18 15-6-6-6 6",key:"153udz"}]]};Wn.node;const Vn=O(Wn);const qn={name:"chevrons-down-up",size:24,node:[["path",{d:"m7 20 5-5 5 5",key:"13a0gw"}],["path",{d:"m7 4 5 5 5-5",key:"1kwcof"}]]};qn.node;const Rl=O(qn);const Gn={name:"chevrons-up-down",size:24,node:[["path",{d:"m7 15 5 5 5-5",key:"1hf1tw"}],["path",{d:"m7 9 5-5 5 5",key:"sgt6xg"}]]};Gn.node;const Pl=O(Gn);const Kn={name:"circle-alert",size:24,node:[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["line",{x1:"12",x2:"12",y1:"8",y2:"12",key:"1pkeuh"}],["line",{x1:"12",x2:"12.01",y1:"16",y2:"16",key:"4dfq90"}]],aliases:["alert-circle"]};Kn.node;const Dl=O(Kn);const Jn={name:"circle-check",size:24,node:[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m16 9-5.5 5.5L8 12",key:"xofnsj"}]],aliases:["check-circle-2"]};Jn.node;const Xe=O(Jn);const Yn={name:"clock-alert",size:24,node:[["path",{d:"M12 6v6l4 2",key:"mmk7yg"}],["path",{d:"M20 12v5",key:"12wsvk"}],["path",{d:"M20 21h.01",key:"1p6o6n"}],["path",{d:"M21.25 8.2A10 10 0 1 0 16 21.16",key:"17fp9f"}]]};Yn.node;const Ll=O(Yn);const Xn={name:"clock",size:24,node:[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 6v6l4 2",key:"mmk7yg"}]]};Xn.node;const Qn=O(Xn);const Zn={name:"cloud",size:24,node:[["path",{d:"M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z",key:"p7xjir"}]]};Zn.node;const bs=O(Zn);const ea={name:"copy",size:24,node:[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]]};ea.node;const Lt=O(ea);const ta={name:"download",size:24,node:[["path",{d:"M12 15V3",key:"m9g1x1"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["path",{d:"m7 10 5 5 5-5",key:"brsn70"}]]};ta.node;const Tl=O(ta);const sa={name:"external-link",size:24,node:[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]]};sa.node;const na=O(sa);const aa={name:"file-text",size:24,node:[["path",{d:"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",key:"1oefj6"}],["path",{d:"M14 2v5a1 1 0 0 0 1 1h5",key:"wfsgrz"}],["path",{d:"M10 9H8",key:"b1mrlr"}],["path",{d:"M16 13H8",key:"t4e002"}],["path",{d:"M16 17H8",key:"z1uh3a"}]]};aa.node;const oa=O(aa);const ra={name:"files",size:24,node:[["path",{d:"M15 2h-4a2 2 0 0 0-2 2v11a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V8",key:"14sh0y"}],["path",{d:"M16.706 2.706A2.4 2.4 0 0 0 15 2v5a1 1 0 0 0 1 1h5a2.4 2.4 0 0 0-.706-1.706z",key:"1970lx"}],["path",{d:"M5 7a2 2 0 0 0-2 2v11a2 2 0 0 0 2 2h8a2 2 0 0 0 1.732-1",key:"l4dndm"}]]};ra.node;const Ml=O(ra);const la={name:"folder-open",size:24,node:[["path",{d:"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2",key:"usdka0"}]]};la.node;const Tt=O(la);const ia={name:"folder",size:24,node:[["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z",key:"1kt360"}]]};ia.node;const ca=O(ia);const da={name:"git-branch",size:24,node:[["path",{d:"M15 6a9 9 0 0 0-9 9V3",key:"1cii5b"}],["circle",{cx:"18",cy:"6",r:"3",key:"1h7g24"}],["circle",{cx:"6",cy:"18",r:"3",key:"fqmcym"}]]};da.node;const Il=O(da);const ua={name:"git-commit-horizontal",size:24,node:[["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}],["line",{x1:"3",x2:"9",y1:"12",y2:"12",key:"1dyftd"}],["line",{x1:"15",x2:"21",y1:"12",y2:"12",key:"oup4p8"}]],aliases:["git-commit"]};ua.node;const Al=O(ua);const ha={name:"git-fork",size:24,node:[["circle",{cx:"12",cy:"18",r:"3",key:"1mpf1b"}],["circle",{cx:"6",cy:"6",r:"3",key:"1lh9wr"}],["circle",{cx:"18",cy:"6",r:"3",key:"1h7g24"}],["path",{d:"M18 9v2c0 .6-.4 1-1 1H7c-.6 0-1-.4-1-1V9",key:"1uq4wg"}],["path",{d:"M12 12v3",key:"158kv8"}]]};ha.node;const wt=O(ha);const ma={name:"globe",size:24,node:[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20",key:"13o1zl"}],["path",{d:"M2 12h20",key:"9i4pu4"}]]};ma.node;const Mt=O(ma);const pa={name:"import",size:24,node:[["path",{d:"M12 3v12",key:"1x0j5s"}],["path",{d:"m8 11 4 4 4-4",key:"1dohi6"}],["path",{d:"M8 5H4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-4",key:"1ywtjm"}]]};pa.node;const _l=O(pa);const fa={name:"info",size:24,node:[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 16v-4",key:"1dtifu"}],["path",{d:"M12 8h.01",key:"e9boi3"}]]};fa.node;const zl=O(fa);const ga={name:"key-round",size:24,node:[["path",{d:"M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z",key:"1s6t7t"}],["circle",{cx:"16.5",cy:"7.5",r:".5",fill:"currentColor",key:"w0ekpg"}]]};ga.node;const Fl=O(ga);const xa={name:"laptop",size:24,node:[["path",{d:"M18 5a2 2 0 0 1 2 2v8.526a2 2 0 0 0 .212.897l1.068 2.127a1 1 0 0 1-.9 1.45H3.62a1 1 0 0 1-.9-1.45l1.068-2.127A2 2 0 0 0 4 15.526V7a2 2 0 0 1 2-2z",key:"1pdavp"}],["path",{d:"M20.054 15.987H3.946",key:"14rxg9"}]]};xa.node;const ys=O(xa);const va={name:"loader-circle",size:24,node:[["path",{d:"M21 12a9 9 0 1 1-6.219-8.56",key:"13zald"}]],aliases:["loader-2"]};va.node;const Jt=O(va);const ja={name:"lock",size:24,node:[["rect",{width:"18",height:"11",x:"3",y:"11",rx:"2",ry:"2",key:"1w4ew1"}],["path",{d:"M7 11V7a5 5 0 0 1 10 0v4",key:"fwvmzm"}]]};ja.node;const Ol=O(ja);const ba={name:"package",size:24,node:[["path",{d:"M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z",key:"1a0edw"}],["path",{d:"M12 22V12",key:"d0xqtd"}],["polyline",{points:"3.29 7 12 12 20.71 7",key:"ousv84"}],["path",{d:"m7.5 4.27 9 5.15",key:"1c824w"}]]};ba.node;const Ul=O(ba);const ya={name:"panel-left-close",size:24,node:[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M9 3v18",key:"fh3hqa"}],["path",{d:"m16 15-3-3 3-3",key:"14y99z"}]],aliases:["sidebar-close"]};ya.node;const Hl=O(ya);const Na={name:"refresh-cw",size:24,node:[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]]};Na.node;const Ct=O(Na);const wa={name:"scan-search",size:24,node:[["path",{d:"M3 7V5a2 2 0 0 1 2-2h2",key:"aa7l1z"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2",key:"4qcy5o"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2",key:"6vwrx8"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2",key:"ioqczr"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}],["path",{d:"m16 16-1.9-1.9",key:"1dq9hf"}]]};wa.node;const Bl=O(wa);const Ca={name:"scroll-text",size:24,node:[["path",{d:"M15 12h-5",key:"r7krc0"}],["path",{d:"M15 8h-5",key:"1khuty"}],["path",{d:"M19 17V5a2 2 0 0 0-2-2H4",key:"zz82l3"}],["path",{d:"M8 21h12a2 2 0 0 0 2-2v-1a1 1 0 0 0-1-1H11a1 1 0 0 0-1 1v1a2 2 0 1 1-4 0V5a2 2 0 1 0-4 0v2a1 1 0 0 0 1 1h3",key:"1ph1d7"}]]};Ca.node;const ka=O(Ca);const Sa={name:"search",size:24,node:[["path",{d:"m21 21-4.34-4.34",key:"14j7rj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}]]};Sa.node;const at=O(Sa);const Ea={name:"settings",size:24,node:[["path",{d:"M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915",key:"1i5ecw"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]]};Ea.node;const $a=O(Ea);const Ra={name:"trash",size:24,node:[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],aliases:["trash-2"]};Ra.node;const Wl=O(Ra);const Pa={name:"triangle-alert",size:24,node:[["path",{d:"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3",key:"wmoenq"}],["path",{d:"M12 9v4",key:"juzpu7"}],["path",{d:"M12 17h.01",key:"p32p05"}]],aliases:["alert-triangle"]};Pa.node;const Ns=O(Pa);const Da={name:"unlink",size:24,node:[["path",{d:"m18.84 12.25 1.72-1.71h-.02a5.004 5.004 0 0 0-.12-7.07 5.006 5.006 0 0 0-6.95 0l-1.72 1.71",key:"yqzxt4"}],["path",{d:"m5.17 11.75-1.71 1.71a5.004 5.004 0 0 0 .12 7.07 5.006 5.006 0 0 0 6.95 0l1.71-1.71",key:"4qinb0"}],["line",{x1:"8",x2:"8",y1:"2",y2:"5",key:"1041cp"}],["line",{x1:"2",x2:"5",y1:"8",y2:"8",key:"14m1p5"}],["line",{x1:"16",x2:"16",y1:"19",y2:"22",key:"rzdirn"}],["line",{x1:"19",x2:"22",y1:"16",y2:"16",key:"ox905f"}]]};Da.node;const ws=O(Da),Vl={currentProject:"default",projects:["default"],docs:[],selectedDocId:null,selectedDoc:null,freshnessResult:null,searchQuery:"",searchResults:[],hasReceivedInitialState:!1,searchAllProjects:!1,historyEntries:null,historyVersionContent:null,exportBundles:[],readOnly:!1,syncEnabled:!1,codeSourceMigrationPending:!1,codeSourcesVersion:0,publicationsVersion:0,commentsVersion:0,commentSummary:{project:"",docs:{}}};let A={...Vl},jt=[];function Q(){jt.forEach(t=>t())}function X(){const[,t]=i.useState(0),s=i.useCallback(()=>{const n=()=>t(a=>a+1);return jt.push(n),()=>{jt=jt.filter(a=>a!==n)}},[]);return i.useState(()=>s()),{...A,setProjects:n=>{A={...A,projects:n},Q()},setCurrentProject:n=>{A={...A,currentProject:n},Q()},setDocs:n=>{A={...A,docs:n},Q()},setSelectedDocId:n=>{A={...A,selectedDocId:n,freshnessResult:null},Q()},setSelectedDoc:n=>{A={...A,selectedDoc:n},Q()},setFreshnessResult:n=>{A={...A,freshnessResult:n},Q()},setSearchQuery:n=>{A={...A,searchQuery:n},Q()},setSearchResults:n=>{A={...A,searchResults:n},Q()},clearSearch:()=>{A={...A,searchQuery:"",searchResults:[]},Q()},setSearchAllProjects:n=>{A={...A,searchAllProjects:n},Q()},setHistoryEntries:n=>{A={...A,historyEntries:n,historyVersionContent:null},Q()},setHistoryVersionContent:n=>{A={...A,historyVersionContent:n},Q()},setExportBundles:n=>{A={...A,exportBundles:n},Q()},bumpCodeSourcesVersion:()=>{A={...A,codeSourcesVersion:A.codeSourcesVersion+1},Q()},bumpPublicationsVersion:()=>{A={...A,publicationsVersion:A.publicationsVersion+1},Q()},bumpCommentsVersion:()=>{A={...A,commentsVersion:A.commentsVersion+1},Q()},setCommentSummary:(n,a)=>{A={...A,commentSummary:{project:n,docs:a}},Q()},setCodeSourceMigrationPending:n=>{A={...A,codeSourceMigrationPending:n},Q()},applyInitialState:n=>{const a=n.projects??n.config?.projects??A.projects,o=a.length===A.projects.length&&a.every((r,l)=>r===A.projects[l]);A={...A,projects:o?A.projects:a,docs:n.docs??A.docs,exportBundles:n.bundles??A.exportBundles,readOnly:n.readOnly??A.readOnly,syncEnabled:n.syncEnabled??A.syncEnabled,codeSourceMigrationPending:n.codeSourceMigrationPending??A.codeSourceMigrationPending,hasReceivedInitialState:!0},Q()}}}function ne(t,s){const n=encodeURIComponent(t);if(!s)return`/${n}`;const a=s.split("/").filter(Boolean).map(o=>encodeURIComponent(o)).join("/");return a?`/${n}/${a}`:`/${n}`}function Ws(t){const s=t.replace(/^\/+|\/+$/g,"");if(!s)return{project:null,docId:null};const n=s.split("/").filter(Boolean);if(n.length===0)return{project:null,docId:null};const a=decodeURIComponent(n[0]);if(n.length===1)return{project:a,docId:null};const o=n.slice(1).map(r=>decodeURIComponent(r)).join("/");return{project:a,docId:o}}function ql(t){try{return decodeURIComponent(t)}catch{return t}}function xe(t){return t.split("/").filter(Boolean).map(s=>encodeURIComponent(s)).join("/")}const bt="/_logs";function kt(t){return`${bt}/${t}`}const La="/_publications";function Cs(t){return t.replace(/\/+$/,"")===La}function Ta(t){const s=t.replace(/\/+$/,"");return s!==bt&&!s.startsWith(`${bt}/`)?null:s.slice(bt.length+1)==="github"?"github":"server"}const Ma=t=>`mcp-documentor:expanded-folders:${t}`;function Vs(t){try{const s=JSON.parse(localStorage.getItem(Ma(t))??"null");return s&&typeof s=="object"&&!Array.isArray(s)?s:{}}catch{return{}}}function Gl(t,s){try{localStorage.setItem(Ma(t),JSON.stringify(s))}catch{}}function Ia(t,s,n,a){const o=new URLSearchParams;s&&o.set("flat","1"),n&&o.set("headers","1"),o.set("project",a);const r=o.toString(),l=document.createElement("a");l.href=`/api/export-zip/${t.id}${r?`?${r}`:""}`,l.download=t.zipFilename,l.click()}function Kl({bundle:t,onClose:s}){const[n,a]=i.useState(!1),[o,r]=i.useState(!1),{currentProject:l}=X();return e.jsx("div",{className:"settings-overlay",onClick:s,children:e.jsxs("div",{className:"settings-popover export-bundle-modal",onClick:c=>c.stopPropagation(),children:[e.jsx("h2",{className:"settings-title",children:t.name}),t.description&&e.jsx("p",{className:"export-bundle-modal-desc",children:t.description}),e.jsx("div",{className:"export-bundle-modal-meta",children:e.jsxs("span",{className:"export-bundle-modal-filename",children:["📦 ",t.zipFilename]})}),e.jsxs("div",{className:"export-bundle-modal-section",children:[e.jsxs("div",{className:"export-bundle-modal-section-title",children:["Documents inclus (",t.docs.length,")"]}),e.jsx("ul",{className:"export-bundle-modal-docs",children:t.docs.map(c=>e.jsx("li",{className:"export-bundle-modal-doc-item",children:e.jsx("span",{className:"export-bundle-modal-doc-ref",children:c})},c))})]}),e.jsxs("div",{className:"export-bundle-modal-toggle-row",children:[e.jsx("span",{className:"export-bundle-modal-toggle-label",children:"Ne pas conserver l'arborescence"}),e.jsx("button",{role:"switch","aria-checked":n,className:`toggle-switch${n?" toggle-switch--on":""}`,onClick:()=>a(c=>!c)})]}),e.jsxs("div",{className:"export-bundle-modal-toggle-row",children:[e.jsx("span",{className:"export-bundle-modal-toggle-label",children:"Inclure les entêtes (métadonnées)"}),e.jsx("button",{role:"switch","aria-checked":o,className:`toggle-switch${o?" toggle-switch--on":""}`,onClick:()=>r(c=>!c)})]}),e.jsxs("div",{className:"settings-actions",children:[e.jsx("button",{className:"settings-cancel-btn",onClick:s,children:"Fermer"}),e.jsx("button",{className:"settings-save-btn",onClick:()=>{Ia(t,n,o,l),s()},children:"↓ Télécharger ZIP"})]})]})})}function Jl(){const{exportBundles:t,currentProject:s}=X(),[n,a]=i.useState(null);return t.length===0?e.jsx("div",{className:"nav-empty",children:"No export bundles yet."}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"export-bundles-list",children:t.map(o=>e.jsxs("div",{className:"export-bundle-item",onClick:()=>a(o),children:[e.jsxs("div",{className:"export-bundle-info",children:[e.jsx("span",{className:"export-bundle-name",children:o.name}),o.description&&e.jsx("span",{className:"export-bundle-desc",children:o.description}),e.jsxs("span",{className:"export-bundle-meta",children:[o.docs.length," doc",o.docs.length!==1?"s":""]})]}),e.jsx("button",{className:"export-bundle-btn",onClick:r=>{r.stopPropagation(),Ia(o,!1,!1,s)},title:`Télécharger ${o.zipFilename}`,children:"↓ ZIP"})]},o.id))}),n&&e.jsx(Kl,{bundle:n,onClose:()=>a(null)})]})}const Aa="mcp-documentor:project";function qs(){try{return localStorage.getItem(Aa)}catch{return null}}function Yl(t){try{localStorage.setItem(Aa,t)}catch{}}async function _a(t){try{const s=await fetch(`/api/docs?project=${encodeURIComponent(t)}`);return s.ok?(await s.json()).docs??[]:[]}catch{return[]}}async function Xl(t){try{const s=await fetch("/api/projects",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({project:t})});return s.ok?{ok:!0,projects:(await s.json()).projects}:{ok:!1}}catch{return{ok:!1}}}function Ql(t){const s=t.split(/[^a-zA-Z0-9]+/).filter(Boolean);return s.length===0?"?":(s.length>1?s[0][0]+s[1][0]:s[0].slice(0,2)).toUpperCase()}function Zl(t){let s=0;for(const n of t)s=s*31+n.charCodeAt(0)>>>0;return`hsl(${s%360}, 52%, 46%)`}async function de(t,s){const n=await fetch(t,s);let a=null;try{a=await n.json()}catch{}if(!n.ok)throw new Error(a?.error??`HTTP ${n.status}`);return a}const Oe=t=>({method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});async function za(){return(await de("/api/code-sources")).projects}async function ei(t,s){return(await de("/api/code-sources/search",{...Oe({query:t}),signal:s})).results}function ti(t,s,n){return de("/api/code-sources/inspect",{...Oe({repo:t,branch:s}),signal:n})}function si(t,s,n,a){return de("/api/code-sources/preview",{...Oe({project:t,config:s,codeRoot:n}),signal:a})}function ni(t,s,n){return de("/api/code-sources/apply",Oe({project:t,config:s,codeRoot:n}))}function ai(t,s){return de("/api/code-roots/inspect",{...Oe({path:t}),signal:s})}function oi(){return de("/api/code-roots")}function ri(t){return de("/api/code-roots/apply",Oe({path:t}))}function li(){return de("/api/github-token")}async function Fa(){return(await de("/api/code-source-migration")).report}function ii(){return de("/api/code-source-migration/ack",{method:"POST"})}function Gs(t){const s=t.config;return s?s.kind==="github"?`${s.repo} · ${s.branch??"default branch"}`:t.codeRoot?`Local · ${t.codeRoot}`:"Local working copy":"Settings unreadable"}function ci({source:t,size:s,active:n}){if(t?.error)return e.jsx(Ns,{size:s,className:"source-icon error"});const a=`source-icon${n?" active":""}`;return t?.config?.kind==="github"?e.jsx(bs,{size:s,className:a}):e.jsx(ys,{size:s,className:a})}function Ks({project:t,size:s}){return e.jsx("span",{className:"project-avatar",style:{width:s,height:s,background:Zl(t),fontSize:Math.round(s*.36)},children:Ql(t)})}function Oa({variant:t,onOpenSettings:s}){const n=re(),{currentProject:a,projects:o,applyInitialState:r,codeSourcesVersion:l}=X(),[c,d]=i.useState(""),[u,m]=i.useState(!1),[h,p]=i.useState(!1),[f,k]=i.useState(0),[v,g]=i.useState(""),[y,N]=i.useState({}),j=i.useRef(null),b=i.useRef(null),E=i.useRef(null),D=v.trim().toLowerCase(),$=D?o.filter(T=>T.toLowerCase().includes(D)):o,w=i.useCallback(()=>{za().then(T=>N(Object.fromEntries(T.map(V=>[V.project,V])))).catch(()=>{})},[]);i.useEffect(w,[l,o,w]),i.useEffect(()=>{h&&w()},[h,w]),i.useEffect(()=>{h&&!u&&E.current?.focus()},[h,u]),i.useEffect(()=>{j.current?.querySelector(`[data-index="${f}"]`)?.scrollIntoView({block:"nearest"})},[f]);const S=T=>{n(ne(T,null))},I=()=>{k(Math.max(0,o.indexOf(a))),g(""),m(!1),p(!0)},x=()=>{p(!1),m(!1),b.current?.focus()},P=T=>{x(),S(T)},F=T=>{p(!1),s(T)},B=T=>{g(T),k(0)},W=T=>{T.key==="ArrowDown"?(T.preventDefault(),k(V=>Math.min($.length-1,V+1))):T.key==="ArrowUp"?(T.preventDefault(),k(V=>Math.max(0,V-1))):T.key==="Enter"?(T.preventDefault(),$[f]&&P($[f])):(T.key==="Escape"||T.key==="Tab")&&x()},G=async()=>{const T=c.trim().replace(/[^a-zA-Z0-9_-]/g,"-");if(!T)return;const{ok:V,projects:Y}=await Xl(T);V&&(Y&&r({projects:Y}),d(""),x(),S(T))},L=y[a],q=L?`${a} — ${L.error??Gs(L)}`:a;return e.jsxs("div",{className:`project-selector project-selector--${t}`,children:[e.jsxs("button",{ref:b,className:`project-trigger${h?" open":""}${L?.error?" error":""}`,onClick:()=>h?x():I(),onKeyDown:T=>{T.key==="ArrowDown"&&!h&&(T.preventDefault(),I())},title:q,"aria-haspopup":"listbox","aria-expanded":h,children:[e.jsx(Ks,{project:a,size:t==="rail"?32:28}),t==="card"&&e.jsxs(e.Fragment,{children:[e.jsxs("span",{className:"project-trigger-text",children:[e.jsx("span",{className:"project-trigger-label",children:a}),e.jsx("span",{className:`project-trigger-caption${L?.error?" error":""}`,children:L?.error?"Code source to fix":"Current project"})]}),e.jsx(Pl,{size:14,className:"project-trigger-caret"})]})]}),h&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"menu-backdrop",onClick:x}),e.jsxs("div",{className:"project-menu",children:[e.jsx("div",{className:"project-menu-label",children:"Projects · code source"}),e.jsxs("div",{className:"project-menu-search",children:[e.jsx(at,{size:14,className:"project-menu-search-icon"}),e.jsx("input",{ref:E,className:"project-menu-search-input",type:"text",placeholder:"Search projects",value:v,onChange:T=>B(T.target.value),onKeyDown:W,role:"combobox","aria-expanded":!0,"aria-controls":"project-menu-list","aria-activedescendant":$.length?`project-option-${f}`:void 0})]}),e.jsxs("div",{id:"project-menu-list",className:"project-menu-list",role:"listbox",tabIndex:-1,ref:j,onKeyDown:W,"aria-activedescendant":$.length?`project-option-${f}`:void 0,children:[$.length===0&&e.jsx("div",{className:"project-menu-empty",children:"No matching project"}),$.map((T,V)=>{const Y=y[T],be=T===a;return e.jsxs("div",{id:`project-option-${V}`,"data-index":V,role:"option","aria-selected":be,className:`project-option${be?" current":""}${V===f?" highlighted":""}`,onMouseEnter:()=>k(V),onClick:()=>P(T),children:[e.jsx(Ks,{project:T,size:24}),e.jsxs("div",{className:"project-option-text",children:[e.jsx("span",{className:"project-option-name",children:T}),Y&&e.jsxs("span",{className:`project-option-source${Y.error?" error":""}`,children:[e.jsx(ci,{source:Y,size:11,active:Y.config?.kind==="github"}),Y.error??Gs(Y)]})]}),Y?.error?e.jsx("button",{className:"project-option-fix",onClick:ue=>{ue.stopPropagation(),F(T)},children:"Fix"}):e.jsxs(e.Fragment,{children:[be&&e.jsx(Ee,{size:14,className:"project-option-check"}),e.jsx("button",{className:"project-option-gear",title:`Settings of ${T}`,onClick:ue=>{ue.stopPropagation(),F(T)},children:e.jsx($a,{size:14})})]})]},T)})]}),e.jsx("div",{className:"project-menu-footer",children:u?e.jsxs("div",{className:"new-project-row",children:[e.jsx("input",{className:"new-project-input",type:"text",placeholder:"New project",value:c,autoFocus:!0,onChange:T=>d(T.target.value),onKeyDown:T=>{T.key==="Enter"&&G(),T.key==="Escape"&&m(!1)}}),e.jsx("button",{className:"new-project-btn",onClick:G,title:"Create project",children:e.jsx(Ee,{size:14})})]}):e.jsxs("button",{className:"project-menu-action",onClick:()=>m(!0),children:[e.jsx(ln,{size:14}),"New project"]})})]})]})]})}function di({focusToken:t}){const s=re(),n=i.useRef(null),{searchQuery:a,searchResults:o,searchAllProjects:r,setSearchAllProjects:l,setSearchQuery:c,setSearchResults:d,clearSearch:u,currentProject:m,selectedDocId:h}=X(),[p,f]=i.useState(a);i.useEffect(()=>{n.current?.focus(),n.current?.select()},[t]);const k=async()=>{if(p.trim()){c(p);try{const N=await(await fetch("/api/search",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({query:p,top_k:10,all_projects:r,project:m})})).json();d(N.results||[])}catch{d([])}}},v=()=>{f(""),u(),s(ne(m,null))},g=y=>{y.key==="Enter"&&k(),y.key==="Escape"&&p&&v()};return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"search-box",children:[e.jsxs("div",{className:"search-field",children:[e.jsx(at,{size:14,className:"search-field-icon"}),e.jsx("input",{ref:n,className:"search-input",type:"text",placeholder:"Search documentation",value:p,onChange:y=>f(y.target.value),onKeyDown:g}),p?e.jsx("button",{className:"search-clear-btn",onClick:v,title:"Clear search",children:"✕"}):e.jsx("span",{className:"search-kbd",children:"⌘K"})]}),e.jsxs("div",{className:"segmented",role:"radiogroup","aria-label":"Search scope",children:[e.jsx("button",{role:"radio","aria-checked":!r,className:`segmented-option${r?"":" active"}`,onClick:()=>l(!1),children:"This project"}),e.jsx("button",{role:"radio","aria-checked":r,className:`segmented-option${r?" active":""}`,onClick:()=>l(!0),children:"All projects"})]})]}),a&&o.length===0&&e.jsx("div",{className:"nav-empty",children:"No match."}),o.map(y=>{const N=y.project??m,j=h===y.id&&m===N;return e.jsxs("div",{className:`search-result${j?" active":""}`,onClick:()=>s(ne(N,y.id)),children:[e.jsxs("div",{className:"search-result-head",children:[e.jsx("span",{className:"search-result-title",children:y.title}),e.jsxs("span",{className:"search-result-score",children:[(y.score*100).toFixed(0),"%"]})]}),y.project&&e.jsxs("div",{className:"search-result-meta",children:["Project: ",y.project]}),e.jsxs("div",{className:"search-result-excerpt",children:[y.excerpt.substring(0,80),"..."]})]},`${N}::${y.id}`)})]})}function ui(t){const s=[],n=new Map;for(const a of t){if(!a.folder){s.push(a);continue}const o=a.folder.split("/").filter(Boolean);let r=n,l="";for(let c=0;c<o.length;c++){const d=o[c];l=l?`${l}/${d}`:d,r.has(d)||r.set(d,{name:d,path:l,children:new Map,docs:[]});const u=r.get(d);c===o.length-1?u.docs.push(a):r=u.children}}return{rootDocs:s,folders:n}}function Ua(t){let s=t.docs.length;for(const n of t.children.values())s+=Ua(n);return s}function Ha(t){return t.docs.some(s=>s.isStale)||[...t.children.values()].some(Ha)}function Ba(t,s){return t.docs.some(n=>(s[n.id]?.unread??0)>0)||[...t.children.values()].some(n=>Ba(n,s))}function Wa(){const{commentSummary:t,currentProject:s}=X();return t.project===s?t.docs:{}}function Va(t){return[...t.values()].flatMap(s=>[s.path,...Va(s.children)])}function hi(t){if(!t)return"";const s=new Date(t),n=a=>String(a).padStart(2,"0");return`${s.getFullYear()}-${n(s.getMonth()+1)}-${n(s.getDate())} ${n(s.getHours())}:${n(s.getMinutes())}`}const ns=t=>8+t*16;function yt({doc:t,selectedDocId:s,onSelect:n,depth:a=0,showCreatedAt:o=!1}){const r=Wa()[t.id]?.unread??0,l=ns(a)+16;return e.jsxs("div",{className:`tree-row tree-row--doc${s===t.id?" active":""}`,style:{paddingLeft:l},onClick:()=>n(t.id),title:t.isStale?`${t.title} — outdated`:t.title,children:[r>0&&e.jsxs("span",{className:"tree-comments tree-comments--gutter",style:{right:`calc(100% - ${l-4}px)`},title:`${r} unread comment${r>1?"s":""}`,children:[e.jsx(ds,{size:11}),r]}),e.jsx(oa,{size:14,className:"tree-row-icon"}),e.jsx("span",{className:"tree-row-label",children:t.title}),o&&t.createdAt&&e.jsx("span",{className:"tree-row-meta",children:hi(t.createdAt)}),t.isStale&&e.jsx("span",{className:"stale-dot"})]})}function qa({nodes:t,depth:s,selectedDocId:n,onSelect:a,expanded:o,onToggle:r}){const l=Wa();return e.jsx(e.Fragment,{children:[...t.entries()].sort(([c],[d])=>c.localeCompare(d)).map(([,c])=>{const d=!!o[c.path],u=d?Dt:$l,m=d?Tt:ca;return e.jsxs("div",{children:[e.jsxs("div",{className:"tree-row tree-row--folder",style:{paddingLeft:ns(s)},onClick:()=>r(c.path),children:[e.jsx(u,{size:12,className:"tree-row-chevron"}),e.jsx(m,{size:14,className:"tree-row-icon"}),e.jsx("span",{className:"tree-row-label",children:c.name}),Ba(c,l)&&e.jsx("span",{className:"tree-comments",title:"Contains unread comments",children:e.jsx(ds,{size:11})}),Ha(c)&&e.jsx("span",{className:"stale-dot",title:"Contains outdated docs"}),e.jsx("span",{className:"tree-row-count",children:Ua(c)})]}),d&&e.jsxs("div",{className:"tree-children",style:{"--guide-x":`${ns(s)+6}px`},children:[c.docs.map(h=>e.jsx(yt,{doc:h,selectedDocId:n,onSelect:a,depth:s+1},h.id)),e.jsx(qa,{nodes:c.children,depth:s+1,selectedDocId:n,onSelect:a,expanded:o,onToggle:r})]})]},c.path)})})}function mi({mode:t,searchFocusToken:s,onCreateDoc:n,onOpenProjectSettings:a,onClose:o}){const r=re(),{docs:l,selectedDocId:c,currentProject:d,exportBundles:u,readOnly:m}=X(),[h,p]=i.useState(()=>({project:d,folders:Vs(d)}));h.project!==d&&p({project:d,folders:Vs(d)});const f=h.folders,k=S=>{const I=S(f);Gl(d,I),p({project:d,folders:I})},v=i.useMemo(()=>ui(l),[l]),g=i.useMemo(()=>l.filter(S=>S.isStale),[l]),y=i.useMemo(()=>[...l].sort((S,I)=>{const x=S.createdAt?new Date(S.createdAt).getTime():0;return(I.createdAt?new Date(I.createdAt).getTime():0)-x}),[l]),N=l.find(S=>S.id===c)?.folder,j=i.useMemo(()=>{const S={};let I="";for(const x of(N??"").split("/").filter(Boolean))I=I?`${I}/${x}`:x,S[I]=!0;return{...S,...f}},[N,f]),b=S=>{r(ne(d,S))},E=S=>{k(I=>({...I,[S]:!j[S]}))},D=()=>{k(()=>Object.fromEntries(Va(v.folders).map(S=>[S,!1])))},$={docs:{title:"Documentation",count:`${l.length} doc${l.length===1?"":"s"}`},search:{title:"Search"},outdated:{title:"Outdated",count:String(g.length)},recent:{title:"Recent",count:String(y.length)},exports:{title:"Export bundles",count:String(u.length)}},w=()=>{switch(t){case"search":return e.jsx(di,{focusToken:s});case"exports":return e.jsx(Jl,{});case"recent":return y.length===0?e.jsx("div",{className:"nav-empty",children:"No documentation entries yet."}):y.map(S=>e.jsx(yt,{doc:S,selectedDocId:c,onSelect:b,showCreatedAt:!0},S.id));case"outdated":return g.length===0?e.jsx("div",{className:"nav-empty",children:"All docs are up to date."}):g.map(S=>e.jsx(yt,{doc:S,selectedDocId:c,onSelect:b},S.id));case"docs":return l.length===0?e.jsx("div",{className:"nav-empty",children:"No documentation entries yet."}):e.jsxs(e.Fragment,{children:[e.jsx(qa,{nodes:v.folders,depth:0,selectedDocId:c,onSelect:b,expanded:j,onToggle:E}),v.rootDocs.map(S=>e.jsx(yt,{doc:S,selectedDocId:c,onSelect:b},S.id))]})}};return e.jsxs("div",{className:"nav-panel",children:[e.jsxs("div",{className:"nav-panel-project",children:[e.jsx(Oa,{variant:"card",onOpenSettings:a}),!m&&e.jsx("button",{className:"nav-panel-new",onClick:n,title:"Create a new document manually",children:e.jsx(ln,{size:16})})]}),e.jsxs("div",{className:"nav-panel-heading",children:[e.jsx("span",{className:"nav-panel-title",children:$[t].title}),$[t].count&&e.jsx("span",{className:"nav-panel-count",children:$[t].count}),t==="docs"&&e.jsx("button",{className:"nav-panel-tool",onClick:D,title:"Collapse all folders",children:e.jsx(Rl,{size:15})}),e.jsx("button",{className:"nav-panel-tool",onClick:o,title:"Hide panel",children:e.jsx(Hl,{size:15})})]}),e.jsx("div",{className:"nav-panel-scroll",children:w()})]})}function pi({report:t,trackedFiles:s,onViewCode:n}){if(t.status==="no_tracking")return e.jsx("p",{className:"file-status-view",style:{color:"#8b949e",fontSize:13},children:"No tracked files for this entry."});const a=l=>t.modified.includes(l)?"modified":t.missing.includes(l)?"missing":(t.anchors_lost??[]).includes(l)?"anchors_lost":"ok",o=l=>!!l.sections?.length&&!(t.anchors_lost??[]).includes(l.path),r=l=>{switch(l){case"ok":return e.jsx("span",{className:"status-ok",children:"✓"});case"modified":return e.jsx("span",{className:"status-modified",children:"⚠ Modified"});case"missing":return e.jsx("span",{className:"status-missing",children:"✕ Missing"});case"anchors_lost":return e.jsx("span",{className:"status-anchors-lost",children:"⚠ Anchors lost"});default:return null}};return e.jsxs("div",{className:"file-status-view",style:{marginBottom:16},children:[e.jsxs("h3",{style:{fontSize:14,color:"#8b949e",margin:"0 0 8px 0"},children:["Tracked Files — ",t.status==="stale"?"Stale":"Up to date"]}),e.jsxs("table",{className:"file-status-table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"File"}),e.jsx("th",{children:"Snapshot Date"}),e.jsx("th",{children:"Status"})]})}),e.jsx("tbody",{children:s.map(l=>{const c=a(l.path);return e.jsxs("tr",{onClick:o(l)?()=>n(l.path):void 0,className:o(l)?"file-row file-row--clickable":"file-row",title:o(l)?"Cliquer pour voir le code de la section":void 0,children:[e.jsxs("td",{children:[l.path,o(l)&&e.jsx("span",{className:"file-row-code-hint",children:" 〈/〉"})]}),e.jsx("td",{children:new Date(l.lastModifiedAt).toLocaleString()}),e.jsx("td",{children:r(c)})]},l.path)})})]})]})}function fi(t){return t.startsWith("+++ ")||t.startsWith("--- ")||t.startsWith("diff ")||t.startsWith("index ")?"file-header":t.startsWith("@@")?"hunk":t.startsWith("+")?"added":t.startsWith("-")?"removed":t.startsWith("###")?"section-title":t==="---"?"separator":"context"}function gi(t){return t.split(`
4
- `).map(s=>({type:fi(s),content:s}))}function xi({diffText:t}){const s=gi(t);return e.jsx("div",{className:"diff-viewer",children:e.jsx("pre",{className:"diff-pre",children:s.map((n,a)=>e.jsx("div",{className:`diff-line diff-line--${n.type}`,children:e.jsx("span",{className:"diff-line-content",children:n.content||" "})},a))})})}class vi{diff(s,n,a={}){let o;typeof a=="function"?(o=a,a={}):"callback"in a&&(o=a.callback);const r=this.castInput(s,a),l=this.castInput(n,a),c=this.removeEmpty(this.tokenize(r,a)),d=this.removeEmpty(this.tokenize(l,a));return this.diffWithOptionsObj(c,d,a,o)}diffWithOptionsObj(s,n,a,o){var r;const l=N=>{if(N=this.postProcess(N,a),o){setTimeout(function(){o(N)},0);return}else return N},c=n.length,d=s.length;let u=1,m=c+d;a.maxEditLength!=null&&(m=Math.min(m,a.maxEditLength));const h=(r=a.timeout)!==null&&r!==void 0?r:1/0,p=Date.now()+h,f=[{oldPos:-1,lastComponent:void 0}];let k=this.extractCommon(f[0],n,s,0,a);if(f[0].oldPos+1>=d&&k+1>=c)return l(this.buildValues(f[0].lastComponent,n,s));let v=-1/0,g=1/0;const y=()=>{for(let N=Math.max(v,-u);N<=Math.min(g,u);N+=2){let j;const b=f[N-1],E=f[N+1];b&&(f[N-1]=void 0);let D=!1;if(E){const w=E.oldPos-N;D=E&&0<=w&&w<c}const $=b&&b.oldPos+1<d;if(!D&&!$){f[N]=void 0;continue}if(!$||D&&b.oldPos<E.oldPos?j=this.addToPath(E,!0,!1,0,a):j=this.addToPath(b,!1,!0,1,a),k=this.extractCommon(j,n,s,N,a),j.oldPos+1>=d&&k+1>=c)return l(this.buildValues(j.lastComponent,n,s))||!0;f[N]=j,j.oldPos+1>=d&&(g=Math.min(g,N-1)),k+1>=c&&(v=Math.max(v,N+1))}u++};if(o)(function N(){setTimeout(function(){if(u>m||Date.now()>p)return o(void 0);y()||N()},0)})();else for(;u<=m&&Date.now()<=p;){const N=y();if(N)return N}}addToPath(s,n,a,o,r){const l=s.lastComponent;return l&&!r.oneChangePerToken&&l.added===n&&l.removed===a?{oldPos:s.oldPos+o,lastComponent:{count:l.count+1,added:n,removed:a,previousComponent:l.previousComponent}}:{oldPos:s.oldPos+o,lastComponent:{count:1,added:n,removed:a,previousComponent:l}}}extractCommon(s,n,a,o,r){const l=n.length,c=a.length;let d=s.oldPos,u=d-o,m=0;for(;u+1<l&&d+1<c&&this.equals(a[d+1],n[u+1],r);)u++,d++,m++,r.oneChangePerToken&&(s.lastComponent={count:1,previousComponent:s.lastComponent,added:!1,removed:!1});return m&&!r.oneChangePerToken&&(s.lastComponent={count:m,previousComponent:s.lastComponent,added:!1,removed:!1}),s.oldPos=d,u}equals(s,n,a){return a.comparator?a.comparator(s,n):s===n||!!a.ignoreCase&&s.toLowerCase()===n.toLowerCase()}removeEmpty(s){const n=[];for(let a=0;a<s.length;a++)s[a]&&n.push(s[a]);return n}castInput(s,n){return s}tokenize(s,n){return Array.from(s)}join(s){return s.join("")}postProcess(s,n){return s}get useLongestToken(){return!1}buildValues(s,n,a){const o=[];let r;for(;s;)o.push(s),r=s.previousComponent,delete s.previousComponent,s=r;o.reverse();const l=o.length;let c=0,d=0,u=0;for(;c<l;c++){const m=o[c];if(m.removed)m.value=this.join(a.slice(u,u+m.count)),u+=m.count;else{if(!m.added&&this.useLongestToken){let h=n.slice(d,d+m.count);h=h.map(function(p,f){const k=a[u+f];return k.length>p.length?k:p}),m.value=this.join(h)}else m.value=this.join(n.slice(d,d+m.count));d+=m.count,m.added||(u+=m.count)}}return o}}function Js(t,s){let n;for(n=0;n<t.length&&n<s.length;n++)if(t[n]!=s[n])return t.slice(0,n);return t.slice(0,n)}function Ys(t,s){let n;if(!t||!s||t[t.length-1]!=s[s.length-1])return"";for(n=0;n<t.length&&n<s.length;n++)if(t[t.length-(n+1)]!=s[s.length-(n+1)])return t.slice(-n);return t.slice(-n)}function as(t,s,n){if(t.slice(0,s.length)!=s)throw Error(`string ${JSON.stringify(t)} doesn't start with prefix ${JSON.stringify(s)}; this is a bug`);return n+t.slice(s.length)}function os(t,s,n){if(!s)return t+n;if(t.slice(-s.length)!=s)throw Error(`string ${JSON.stringify(t)} doesn't end with suffix ${JSON.stringify(s)}; this is a bug`);return t.slice(0,-s.length)+n}function Ye(t,s){return as(t,s,"")}function mt(t,s){return os(t,s,"")}function Xs(t,s){return s.slice(0,ji(t,s))}function ji(t,s){let n=0;t.length>s.length&&(n=t.length-s.length);let a=s.length;t.length<s.length&&(a=t.length);const o=Array(a);let r=0;o[0]=0;for(let l=1;l<a;l++){for(s[l]==s[r]?o[l]=o[r]:o[l]=r;r>0&&s[l]!=s[r];)r=o[r];s[l]==s[r]&&r++}r=0;for(let l=n;l<t.length;l++){for(;r>0&&t[l]!=s[r];)r=o[r];t[l]==s[r]&&r++}return r}function Ga(t,s){const n=[];for(const a of Array.from(s.segment(t))){const o=a.segment;n.length&&/\s/.test(n[n.length-1])&&/\s/.test(o)?n[n.length-1]+=o:n.push(o)}return n}function rs(t,s){if(s)return Qe(t,s)[1];let n;for(n=t.length-1;n>=0&&t[n].match(/\s/);n--);return t.substring(n+1)}function Ie(t,s){if(s)return Qe(t,s)[0];const n=t.match(/^\s*/);return n?n[0]:""}function Qe(t,s){if(!s)return[Ie(t),rs(t)];if(s.resolvedOptions().granularity!="word")throw new Error('The segmenter passed must have a granularity of "word"');const n=Ga(t,s),a=n[0],o=n[n.length-1],r=/\s/.test(a)?a:"",l=/\s/.test(o)?o:"";return[r,l]}const Qs="a-zA-Z0-9_\\u{AD}\\u{C0}-\\u{D6}\\u{D8}-\\u{F6}\\u{F8}-\\u{2C6}\\u{2C8}-\\u{2D7}\\u{2DE}-\\u{2FF}\\u{1E00}-\\u{1EFF}",bi=new RegExp(`[${Qs}]+|\\s+|[^${Qs}]`,"ug");class yi extends vi{equals(s,n,a){return a.ignoreCase&&(s=s.toLowerCase(),n=n.toLowerCase()),s.trim()===n.trim()}tokenize(s,n={}){let a;if(n.intlSegmenter){const l=n.intlSegmenter;if(l.resolvedOptions().granularity!="word")throw new Error('The segmenter passed must have a granularity of "word"');a=Ga(s,l)}else a=s.match(bi)||[];const o=[];let r=null;return a.forEach(l=>{/\s/.test(l)?r==null?o.push(l):o.push(o.pop()+l):r!=null&&/\s/.test(r)?o[o.length-1]==r?o.push(o.pop()+l):o.push(r+l):o.push(l),r=l}),o}join(s){return s.map((n,a)=>a==0?n:n.replace(/^\s+/,"")).join("")}postProcess(s,n){if(!s||n.oneChangePerToken)return s;let a=null,o=null,r=null;return s.forEach(l=>{l.added?o=l:l.removed?r=l:((o||r)&&Zs(a,r,o,l,n.intlSegmenter),a=l,o=null,r=null)}),(o||r)&&Zs(a,r,o,null,n.intlSegmenter),s}}const Ni=new yi;function wi(t,s,n){return Ni.diff(t,s,n)}function Zs(t,s,n,a,o){if(s&&n){const[r,l]=Qe(s.value,o),[c,d]=Qe(n.value,o);if(t){const u=Js(r,c);t.value=os(t.value,c,u),s.value=Ye(s.value,u),n.value=Ye(n.value,u)}if(a){const u=Ys(l,d);a.value=as(a.value,d,u),s.value=mt(s.value,u),n.value=mt(n.value,u)}}else if(n){if(t){const r=Ie(n.value,o);n.value=n.value.substring(r.length)}if(a){const r=Ie(a.value,o);a.value=a.value.substring(r.length)}}else if(t&&a){const r=Ie(a.value,o),[l,c]=Qe(s.value,o),d=Js(r,l);s.value=Ye(s.value,d);const u=Ys(Ye(r,d),c);s.value=mt(s.value,u),a.value=as(a.value,r,u),t.value=os(t.value,r,r.slice(0,r.length-u.length))}else if(a){const r=Ie(a.value,o),l=rs(s.value,o),c=Xs(l,r);s.value=mt(s.value,c)}else if(t){const r=rs(t.value,o),l=Ie(s.value,o),c=Xs(r,l);s.value=Ye(s.value,c)}}const Yt={create:"Created",update:"Updated",patch:"Patched",delete:"Deleted",snapshot:"Snapshot"},Xt={create:"➕",update:"📝",patch:"🩹",delete:"🗑️",snapshot:"📸"};function Ci(t,s){const n={};t.title!==s.title&&(n.title={from:t.title,to:s.title});const a=s.tags.filter(f=>!t.tags.includes(f)),o=t.tags.filter(f=>!s.tags.includes(f));(a.length||o.length)&&(n.tags={added:a,removed:o});const r=t.tracked_files.map(f=>f.path),l=s.tracked_files.map(f=>f.path),c=l.filter(f=>!r.includes(f)),d=r.filter(f=>!l.includes(f));(c.length||d.length)&&(n.tracked_files={added:c,removed:d});const u=t.related_docs??[],m=s.related_docs??[],h=m.filter(f=>!u.includes(f)),p=u.filter(f=>!m.includes(f));return(h.length||p.length)&&(n.related_docs={added:h,removed:p}),n}function ki({diff:t}){return e.jsxs("div",{className:"history-meta-diff",children:[e.jsx("span",{className:"history-meta-diff-title",children:"Metadata changes"}),t.title&&e.jsxs("div",{className:"history-meta-diff-row",children:[e.jsx("span",{className:"history-meta-diff-field",children:"Title"}),e.jsx("span",{className:"history-meta-diff-chip--removed",children:t.title.from}),e.jsx("span",{className:"history-meta-diff-arrow",children:"→"}),e.jsx("span",{className:"history-meta-diff-chip--added",children:t.title.to})]}),t.tags&&e.jsxs("div",{className:"history-meta-diff-row",children:[e.jsx("span",{className:"history-meta-diff-field",children:"Tags"}),e.jsxs("div",{className:"history-meta-diff-chips",children:[t.tags.removed.map(s=>e.jsxs("span",{className:"history-meta-diff-chip--removed",children:["− ",s]},s)),t.tags.added.map(s=>e.jsxs("span",{className:"history-meta-diff-chip--added",children:["+ ",s]},s))]})]}),t.tracked_files&&e.jsxs("div",{className:"history-meta-diff-row",children:[e.jsx("span",{className:"history-meta-diff-field",children:"Tracked files"}),e.jsxs("div",{className:"history-meta-diff-chips",children:[t.tracked_files.removed.map(s=>e.jsxs("span",{className:"history-meta-diff-chip--removed",children:["− ",s]},s)),t.tracked_files.added.map(s=>e.jsxs("span",{className:"history-meta-diff-chip--added",children:["+ ",s]},s))]})]}),t.related_docs&&e.jsxs("div",{className:"history-meta-diff-row",children:[e.jsx("span",{className:"history-meta-diff-field",children:"Related docs"}),e.jsxs("div",{className:"history-meta-diff-chips",children:[t.related_docs.removed.map(s=>e.jsxs("span",{className:"history-meta-diff-chip--removed",children:["− ",s]},s)),t.related_docs.added.map(s=>e.jsxs("span",{className:"history-meta-diff-chip--added",children:["+ ",s]},s))]})]})]})}function Si({changes:t}){return e.jsx("div",{className:"history-inline-diff",children:t.map((s,n)=>s.added?e.jsx("span",{className:"history-inline-diff--added",children:s.value},n):s.removed?e.jsx("span",{className:"history-inline-diff--removed",children:s.value},n):e.jsx("span",{children:s.value},n))})}function Ei(t){const s=[],n=[];let a=null;for(const o of t)o.changeType==="snapshot"?(a={snapshot:o,subEntries:[]},n.push(a)):a===null?s.push(o):a.subEntries.push(o);return{uncommitted:s,groups:n}}function $i({docId:t,project:s,entries:n,selectedVersion:a,onSelectVersion:o,markdownComponents:r}){const[l,c]=i.useState(null),[d,u]=i.useState(!1),[m,h]=i.useState(new Set),{uncommitted:p,groups:f}=i.useMemo(()=>Ei(n),[n]),k=b=>{h(E=>{const D=new Set(E);return D.has(b)?D.delete(b):D.add(b),D})},v=a!==null&&(a.changeType==="update"||a.changeType==="patch"||a.changeType==="snapshot")&&a.version>1,g=(()=>{if(!a||!v)return null;if(a.changeType==="snapshot"){const b=n.filter(E=>E.version<a.version&&E.changeType==="snapshot").sort((E,D)=>D.version-E.version);return b.length>0?b[0].version:Math.min(...n.map(E=>E.version))}return a.version-1})(),y=g!==null?n.find(b=>b.version===g)??null:null,N=y?Ci(y.metadata,a.metadata):null,j=N&&Object.keys(N).length>0;return i.useEffect(()=>{if(c(null),!a||!v||g===null)return;let b=!1;return u(!0),fetch(`/api/history-version/${xe(t)}/${g}?project=${encodeURIComponent(s)}`).then(E=>E.json()).then(E=>{if(b)return;const D=E?.content??"",$=a.content??"";c(wi(D,$))}).catch(()=>{b||c([])}).finally(()=>{b||u(!1)}),()=>{b=!0}},[a?.version]),n.length===0?e.jsx("div",{className:"history-viewer",children:e.jsx("div",{className:"doc-viewer-empty",children:"No version history available for this document."})}):e.jsxs("div",{className:"history-viewer",children:[e.jsxs("div",{className:"history-list",children:[p.length>0&&e.jsxs("div",{className:"history-uncommitted",children:[e.jsx("span",{className:"history-uncommitted-label",children:"Non archivé"}),p.map(b=>{const E=a?.version===b.version,D=new Date(b.changedAt).toLocaleString(),$=Yt[b.changeType]??b.changeType,w=Xt[b.changeType]??"❓";return e.jsxs("button",{className:`history-entry history-entry--sub${E?" history-entry--active":""}`,onClick:()=>o(b.version),children:[e.jsxs("div",{className:"history-entry-header",children:[e.jsxs("span",{className:"history-entry-version",children:["v",b.version]}),e.jsxs("span",{className:`history-entry-type history-entry-type--${b.changeType}`,children:[w," ",$]})]}),e.jsx("span",{className:"history-entry-date",children:D})]},b.version)})]}),f.length===0&&p.length===0&&e.jsx("div",{className:"doc-viewer-empty",children:"No version history available."}),f.map(b=>{const E=a?.version===b.snapshot.version,D=m.has(b.snapshot.version),$=new Date(b.snapshot.changedAt).toLocaleString();return e.jsxs("div",{className:"history-group",children:[e.jsx("div",{className:`history-entry history-entry--snapshot-card${E?" history-entry--active":""}`,children:e.jsxs("button",{className:"history-entry-snapshot-main",onClick:()=>o(b.snapshot.version),children:[e.jsxs("div",{className:"history-entry-header",children:[e.jsxs("span",{className:"history-entry-version",children:["Version ",b.snapshot.version]}),e.jsx("span",{className:"history-entry-type history-entry-type--snapshot",children:"📸 Snapshot"})]}),e.jsxs("div",{className:"history-entry-footer",children:[e.jsx("span",{className:"history-entry-date",children:$}),b.subEntries.length>0&&e.jsx("span",{className:`history-group-toggle${D?" history-group-toggle--open":""}`,onClick:w=>{w.stopPropagation(),k(b.snapshot.version)},role:"button",tabIndex:0,onKeyDown:w=>{(w.key==="Enter"||w.key===" ")&&(w.stopPropagation(),k(b.snapshot.version))},children:D?"Masquer ▲":`Voir les ${b.subEntries.length} modification${b.subEntries.length>1?"s":""} ▼`})]})]})}),D&&e.jsx("div",{className:"history-group-entries",children:b.subEntries.map(w=>{const S=a?.version===w.version,I=new Date(w.changedAt).toLocaleString(),x=Yt[w.changeType]??w.changeType,P=Xt[w.changeType]??"❓";return e.jsxs("button",{className:`history-entry history-entry--sub${S?" history-entry--active":""}`,onClick:()=>o(w.version),children:[e.jsxs("div",{className:"history-entry-header",children:[e.jsxs("span",{className:"history-entry-version",children:["v",w.version]}),e.jsxs("span",{className:`history-entry-type history-entry-type--${w.changeType}`,children:[P," ",x]})]}),e.jsx("span",{className:"history-entry-date",children:I})]},w.version)})})]},b.snapshot.version)})]}),e.jsx("div",{className:"history-content",children:a?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"history-content-meta",children:[e.jsxs("div",{className:"history-content-meta-title",children:[e.jsx("strong",{children:a.metadata.title}),e.jsxs("span",{className:"history-content-version",children:["Version ",a.version]})]}),e.jsxs("div",{className:"history-content-meta-info",children:[e.jsxs("span",{className:`history-entry-type history-entry-type--${a.changeType}`,children:[Xt[a.changeType]??"❓"," ",Yt[a.changeType]??a.changeType]}),e.jsx("span",{className:"history-content-date",children:new Date(a.changedAt).toLocaleString()}),v&&d&&e.jsx("span",{className:"history-diff-loading",children:"Loading diff…"}),v&&!d&&g!==null&&e.jsxs("span",{className:"history-diff-base",children:["vs v",g]})]}),j&&e.jsx(ki,{diff:N})]}),v&&a.changeType==="snapshot"&&!d&&l!==null&&e.jsxs("div",{className:"history-diff-recap-banner",children:["Récapitulatif des modifications effectuées depuis le dernier évènement ",e.jsx("strong",{children:"snapshot"})]}),v?l!==null?e.jsx(Si,{changes:l}):null:e.jsx("div",{className:"doc-content",children:e.jsx(cn,{remarkPlugins:[un],rehypePlugins:[dn],components:r,children:a.content??""})})]}):e.jsx("div",{className:"doc-viewer-empty",children:"Select a version to view its content."})})]})}const Ri={ts:"typescript",tsx:"tsx",js:"javascript",jsx:"jsx",py:"python",rb:"ruby",go:"go",java:"java",rs:"rust",cs:"csharp",cpp:"cpp",c:"c",sh:"bash",bash:"bash",zsh:"bash",json:"json",yaml:"yaml",yml:"yaml",toml:"toml",md:"markdown",css:"css",scss:"scss",html:"html",xml:"xml",sql:"sql"};function Pi(t){const s=t.split(".").pop()?.toLowerCase()??"";return Ri[s]??"text"}function Di({docId:t,project:s,filePath:n,onClose:a}){const[o,r]=i.useState([]),[l,c]=i.useState(!0),[d,u]=i.useState(null);i.useEffect(()=>{const h=new AbortController,p=n.split("/").map(encodeURIComponent).join("/");return fetch(`/api/file-section/${p}?docId=${encodeURIComponent(t)}&project=${encodeURIComponent(s)}`,{signal:h.signal}).then(f=>f.json()).then(f=>{if(f.error)throw new Error(f.error);r(f.sections??[])}).catch(f=>{f.name!=="AbortError"&&u(f.message)}).finally(()=>c(!1)),()=>h.abort()},[t,n]),i.useEffect(()=>{const h=p=>{p.key==="Escape"&&a()};return document.addEventListener("keydown",h),()=>document.removeEventListener("keydown",h)},[a]);const m=Pi(n);return e.jsx("div",{className:"modal-overlay",onClick:a,children:e.jsxs("div",{className:"modal-content",onClick:h=>h.stopPropagation(),children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("span",{className:"modal-title",children:n}),e.jsx("button",{className:"modal-close-btn",onClick:a,children:"✕"})]}),e.jsxs("div",{className:"modal-body",children:[l&&e.jsx("p",{style:{color:"#8b949e",fontSize:13},children:"Loading…"}),d&&e.jsx("p",{style:{color:"#f85149",fontSize:13},children:d}),!l&&!d&&o.map((h,p)=>e.jsxs("div",{children:[e.jsxs("p",{className:"section-code-header",children:["Lines ",h.start,"–",h.end]}),e.jsx(Do,{language:m,style:Lo,customStyle:{margin:0,borderRadius:"6px",fontSize:"13px"},codeTagProps:{style:{fontFamily:"'Fira Code', 'Cascadia Code', Consolas, monospace"}},showLineNumbers:!0,startingLineNumber:h.start,children:h.code})]},p))]})]})})}function Li({project:t,triggerRef:s,onInsert:n,onClose:a}){const[o,r]=i.useState("upload"),[l,c]=i.useState(""),[d,u]=i.useState(""),[m,h]=i.useState(!1),[p,f]=i.useState(null),[k,v]=i.useState([]),[g,y]=i.useState({visibility:"hidden"}),N=i.useRef(null);i.useLayoutEffect(()=>{const $=N.current;if(!$)return;const w=$.offsetHeight,S=360;y({position:"fixed",top:Math.max(8,(window.innerHeight-w)/2),left:Math.max(8,(window.innerWidth-S)/2),width:S,visibility:"visible"})},[s]),i.useEffect(()=>{fetch(`/api/images/${encodeURIComponent(t)}`).then($=>$.json()).then($=>v($)).catch(()=>{})},[t]),i.useEffect(()=>{function $(w){N.current&&!N.current.contains(w.target)&&s.current!==w.target&&a()}return document.addEventListener("mousedown",$),()=>document.removeEventListener("mousedown",$)},[a,s]);const j=i.useCallback(async $=>{h(!0),f(null);try{const w=new FormData;w.append("file",$);const S=await fetch(`/api/images?project=${encodeURIComponent(t)}`,{method:"POST",body:w});if(!S.ok){const x=await S.json().catch(()=>({}));throw new Error(x.error??"Upload failed")}const{url:I}=await S.json();n(`![${l}](${I})`),a()}catch(w){f(w instanceof Error?w.message:"Upload failed")}finally{h(!1)}},[t,l,n,a]),b=async $=>{const w=$.target.files?.[0];w&&await j(w)};i.useEffect(()=>{const $=async w=>{const I=Array.from(w.clipboardData?.items??[]).find(B=>B.type.startsWith("image/"));if(!I)return;w.preventDefault();const x=I.getAsFile();if(!x)return;const P=x.type.split("/")[1]??"png",F=new File([x],`paste-${Date.now()}.${P}`,{type:x.type});await j(F)};return document.addEventListener("paste",$),()=>document.removeEventListener("paste",$)},[j]);const E=()=>{d.trim()&&(n(`![${l}](${d.trim()})`),a())},D=$=>{n(`![${l}](${$})`),a()};return To.createPortal(e.jsxs("div",{className:"image-insert-popover",ref:N,style:g,children:[e.jsxs("div",{className:"image-insert-header",children:[e.jsx("span",{className:"image-insert-title",children:"Insert image"}),e.jsx("button",{className:"image-insert-close",onClick:a,title:"Close",children:"✕"})]}),e.jsxs("div",{className:"image-insert-tabs",children:[e.jsx("button",{className:`image-insert-tab${o==="upload"?" active":""}`,onClick:()=>r("upload"),children:"Upload"}),e.jsx("button",{className:`image-insert-tab${o==="url"?" active":""}`,onClick:()=>r("url"),children:"URL"})]}),e.jsxs("div",{className:"image-insert-alt-row",children:[e.jsx("label",{className:"image-insert-label",children:"Alt text"}),e.jsx("input",{className:"image-insert-input",type:"text",placeholder:"Description (optional)",value:l,onChange:$=>c($.target.value)})]}),o==="upload"?e.jsxs("div",{className:"image-insert-tab-content",children:[e.jsxs("label",{className:`image-upload-label${m?" uploading":""}`,children:[e.jsx("input",{type:"file",accept:"image/*",style:{display:"none"},onChange:b,disabled:m}),m?"⏳ Uploading…":"📁 Choose a file"]}),e.jsx("p",{className:"image-paste-hint",children:"or press Ctrl+V / ⌘V to paste from clipboard"}),p&&e.jsx("div",{className:"image-insert-error",children:p})]}):e.jsxs("div",{className:"image-insert-tab-content",children:[e.jsx("input",{className:"image-insert-input",type:"text",placeholder:"https://example.com/image.png",value:d,onChange:$=>u($.target.value),onKeyDown:$=>$.key==="Enter"&&E()}),e.jsx("button",{className:"image-insert-btn-insert",onClick:E,disabled:!d.trim(),children:"Insert"})]}),k.length>0&&e.jsxs("div",{className:"image-insert-gallery-section",children:[e.jsx("div",{className:"image-insert-gallery-label",children:"Project images"}),e.jsx("div",{className:"image-thumbs",children:k.map($=>e.jsx("img",{src:$.url,alt:$.filename,className:"image-thumb",title:$.filename,onClick:()=>D($.url)},$.filename))})]})]}),document.body)}function en(t,s){return!t||t.status==="no_tracking"?"unknown":t.modified.includes(s)?"modified":t.missing.includes(s)?"missing":(t.anchors_lost??[]).includes(s)?"anchors_lost":t.unchanged.includes(s)?"ok":"unknown"}function Ti(t){if(!t)return"—";const s=new Date(t);if(Number.isNaN(s.getTime()))return"—";const n=a=>String(a).padStart(2,"0");return`${s.toLocaleDateString(void 0,{month:"short",day:"numeric"})}, ${n(s.getHours())}:${n(s.getMinutes())}`}function Mi({doc:t,isStale:s,report:n,toc:a,activeHeadingId:o,version:r,onSelectHeading:l,onSelectFile:c,onClose:d,tab:u,onTab:m,comments:h,unreadComments:p}){const f=re(),{docs:k,projects:v,currentProject:g}=X(),y=j=>!!t.tracked_files.find(E=>E.path===j)?.sections?.length&&en(n,j)!=="anchors_lost",N=h!==null&&u==="comments";return e.jsxs("aside",{className:"context-rail",children:[e.jsxs("div",{className:"rail-section rail-section--toc",children:[e.jsxs("div",{className:"rail-section-head",children:[h!==null?e.jsxs("div",{className:"rail-tabs",children:[e.jsx("button",{type:"button",className:`rail-tab${N?"":" active"}`,onClick:()=>m("page"),children:"On this page"}),e.jsxs("button",{type:"button",className:`rail-tab${N?" active":""}`,onClick:()=>m("comments"),children:["Comments",p>0&&e.jsx("span",{className:"rail-tab-count",children:p})]})]}):e.jsx("span",{className:"rail-label",children:a.length>0?"On this page":""}),e.jsx("button",{className:"rail-collapse-btn",onClick:d,title:"Hide details (Ctrl/⌘ + \\)",children:"▷|"})]}),N&&h,!N&&a.length>0&&e.jsx("nav",{className:"rail-toc",children:a.map(j=>e.jsx("button",{className:`rail-toc-item rail-toc-item--h${j.level}${o===j.id?" active":""}`,onClick:()=>l(j.id),children:j.text},j.id))})]}),!N&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"rail-section",children:[e.jsx("span",{className:"rail-label",children:"Status"}),e.jsxs("div",{className:"rail-row",children:[e.jsx("span",{className:"rail-key",children:"Freshness"}),e.jsx("span",{className:`rail-chip${s?" rail-chip--stale":" rail-chip--fresh"}`,children:s?"Outdated":"Up to date"})]}),e.jsxs("div",{className:"rail-row",children:[e.jsx("span",{className:"rail-key",children:"Last updated"}),e.jsx("span",{className:"rail-val",children:Ti(t.updatedAt)})]}),e.jsxs("div",{className:"rail-row",children:[e.jsx("span",{className:"rail-key",children:"Version"}),e.jsx("span",{className:"rail-val",children:r!==null?`v${r}`:"—"})]})]}),t.tracked_files.length>0&&e.jsxs("div",{className:"rail-section",children:[e.jsxs("span",{className:"rail-label",children:["Tracked files · ",t.tracked_files.length]}),e.jsx("div",{className:"rail-files",children:t.tracked_files.map(j=>{const b=en(n,j.path),E=y(j.path);return e.jsxs("button",{className:`rail-file${E?" rail-file--clickable":""}`,onClick:E?()=>c(j.path):void 0,title:E?`${j.path} — voir le code de la section`:j.path,children:[e.jsx("span",{className:`rail-file-dot rail-file-dot--${b}`}),e.jsx("span",{className:"rail-file-path",children:j.path})]},j.path)})}),e.jsx("div",{className:"rail-legend",children:"modified · up to date · missing · anchors lost"})]}),t.tags.length>0&&e.jsxs("div",{className:"rail-section",children:[e.jsx("span",{className:"rail-label",children:"Tags"}),e.jsx("div",{className:"rail-tags",children:t.tags.map(j=>e.jsx("span",{className:"tag-badge",children:j},j))})]}),t.related_docs&&t.related_docs.length>0&&e.jsxs("div",{className:"rail-section",children:[e.jsx("span",{className:"rail-label",children:"Related pages"}),e.jsx("div",{className:"rail-links",children:t.related_docs.map(j=>{const b=j.indexOf(":");if(b!==-1){const D=j.slice(0,b),$=j.slice(b+1);return v.includes(D)?e.jsxs("button",{className:"rail-link rail-link--cross-project",onClick:()=>f(ne(D,$)),title:`Projet : ${D}`,children:["↗ ",D," · ",$]},j):e.jsxs("span",{className:"rail-link rail-link--broken",children:[j," (projet introuvable)"]},j)}const E=k.find(D=>D.id===j);return E?e.jsxs("button",{className:"rail-link",onClick:()=>f(ne(g,j)),children:["▤ ",E.title]},j):e.jsxs("span",{className:"rail-link rail-link--broken",children:[j," (lien cassé)"]},j)})})]})]})]})}function Qt(t){return!t.root.read||t.replies.some(s=>!s.read)}function Ii(t){return[t.root.id,...t.replies.map(s=>s.id)]}function pt(t){return t===null?"an unversioned publication":`v${t}`}function Ai({data:t,locatedIds:s,activeId:n,hoveredId:a,readOnly:o,onActivate:r,onHover:l,onDelete:c}){const d=Mo(t.comments),u=d.filter(S=>!S.root.detached),m=d.filter(S=>S.root.detached),h=t.comments.filter(S=>!S.read).length,[p,f]=i.useState(h>0?"unread":"all"),[k,v]=i.useState(null),[g,y]=i.useState(!1),[N,j]=i.useState(null),b=t.publication?.id,E=t.publication?.commentsClosed===!0;if(!b)return e.jsx("div",{className:"cp-empty",children:"This document is not published: readers cannot comment on it."});const D=async S=>{y(!0),j(null);try{await S()}catch(I){j(I instanceof Error?I.message:String(I))}finally{y(!1)}},$=p==="unread"?u.filter(Qt):u,w=(S,I)=>{const{root:x}=S,P=Qt(S),F=s.has(x.id);return e.jsxs("div",{className:`cp-card${P?" cp-card--unread":""}${I?" cp-card--detached":""}${n===x.id||a===x.id?" cp-card--active":""}`,onClick:()=>r(x.id),onMouseEnter:()=>l(x.id),onMouseLeave:()=>l(null),children:[e.jsxs("div",{className:"cp-head",children:[I?e.jsx(ws,{size:12,className:"cp-state cp-state--detached"}):P?e.jsx("span",{className:"cp-dot",title:"Unread"}):e.jsx(Ee,{size:12,className:"cp-state cp-state--read"}),e.jsx("span",{className:"cp-author",title:Ls,children:Ts(x.author)}),e.jsxs("span",{className:"cp-time",title:new Date(x.createdAt).toLocaleString(),children:["· ",Ms(x.createdAt)]}),!o&&e.jsxs("span",{className:"cp-actions",onClick:B=>B.stopPropagation(),children:[P&&e.jsx("button",{type:"button",className:"cp-icon",title:"Mark as read",disabled:g,onClick:()=>D(()=>Is(b,Ii(S))),children:e.jsx(Ee,{size:14})}),e.jsx("button",{type:"button",className:"cp-icon cp-icon--danger",title:"Delete",disabled:g,onClick:()=>v(x.id),children:e.jsx(Wl,{size:14})})]})]}),x.anchor&&e.jsxs("div",{className:`cp-quote${F||I?"":" cp-quote--lost"}`,children:["« ",x.anchor.exact," »",I&&x.detached?` — ${pt(x.detached.fromVersion)}`:""]}),!I&&!F&&e.jsx("div",{className:"cp-note",children:"Passage changed since the publication: not highlighted here."}),e.jsx("div",{className:"cp-body",children:x.body}),S.replies.map(B=>e.jsxs("div",{className:`cp-reply${B.read?"":" cp-reply--unread"}`,children:[e.jsxs("div",{className:"cp-reply-head",children:[e.jsx("span",{title:Ls,children:Ts(B.author)})," · ",Ms(B.createdAt)]}),e.jsx("div",{className:"cp-body",children:B.body})]},B.id)),I&&x.detached&&e.jsxs("div",{className:"cp-note",children:["Detached when the publication went from ",pt(x.detached.fromVersion)," to"," ",pt(x.detached.toVersion)]}),k===x.id&&e.jsxs("div",{className:"cp-confirm",onClick:B=>B.stopPropagation(),children:[e.jsxs("span",{children:["Delete this comment",S.replies.length>0?` and its ${S.replies.length} replies`:"","?"]}),e.jsx("button",{type:"button",className:"cp-confirm-btn",onClick:()=>v(null),disabled:g,children:"Cancel"}),e.jsx("button",{type:"button",className:"cp-confirm-btn cp-confirm-btn--danger",disabled:g,onClick:()=>{v(null),j(null),c(b,[x.id]).catch(B=>j(B instanceof Error?B.message:String(B)))},children:"Delete"})]})]},x.id)};return e.jsxs("div",{className:"cp",children:[e.jsxs("div",{className:"cp-toolbar",children:[e.jsxs("button",{type:"button",className:`cp-filter${p==="unread"?" active":""}`,onClick:()=>f("unread"),children:["Unread · ",d.filter(Qt).length]}),e.jsxs("button",{type:"button",className:`cp-filter${p==="all"?" active":""}`,onClick:()=>f("all"),children:["All · ",u.length]}),!o&&h>0&&e.jsx("button",{type:"button",className:"cp-mark-all",disabled:g,onClick:()=>D(()=>Is(b,null)),children:"Mark all as read"})]}),e.jsxs("div",{className:"cp-usage",children:[e.jsxs("span",{children:[t.comments.length," / ",t.limit," comments on the published ",pt(t.publication?.version??null),E&&" · closed to new comments"]}),!o&&e.jsx("button",{type:"button",className:"cp-close-toggle",disabled:g,title:E?"Let readers add comments again":"Readers keep seeing the comments but can no longer add any",onClick:()=>D(()=>Io(b,!E)),children:E?"Reopen comments":"Close comments"})]}),N&&e.jsx("div",{className:"cp-error",children:N}),$.length===0?m.length===0&&e.jsx("div",{className:"cp-empty",children:p==="unread"?"No unread comment.":"No comment yet."}):$.map(S=>w(S,!1)),m.length>0&&e.jsxs("div",{className:"cp-detached",children:[e.jsxs("span",{className:"rail-label",children:["Detached · ",m.length]}),e.jsx("div",{className:"cp-detached-text",children:"Their passage is absent from the published version: readers no longer see them. They still count toward the limit until deleted."}),m.map(S=>w(S,!0))]})]})}function _i(t,s){const{commentsVersion:n,publicationsVersion:a}=X(),[o,r]=i.useState(null),[l,c]=i.useState(0),[d,u]=i.useState(new Set),m=`${t}\0${s??""}`;i.useEffect(()=>{if(!s)return;let v=!1;return Ao(t,s).then(g=>{v||r({key:m,data:g})}).catch(g=>console.error(`Comments of "${s}" could not be loaded: ${g.message}`)),()=>{v=!0}},[m,t,s,n,a,l]);const h=i.useCallback(()=>c(v=>v+1),[]),p=i.useCallback(async(v,g)=>{u(y=>new Set([...y,...g]));try{await _o(v,g)}catch(y){throw u(N=>new Set([...N].filter(j=>!g.includes(j)))),y}},[]),f=o?.key===m?o.data:null;return{data:i.useMemo(()=>{if(!f||d.size===0)return f;const v=f.comments.filter(g=>!d.has(g.id)&&!(g.parentId&&d.has(g.parentId)));return v.length===f.comments.length?f:{...f,comments:v}},[f,d]),reload:h,remove:p}}function zi(){const{currentProject:t,commentsVersion:s,publicationsVersion:n,hasReceivedInitialState:a,setCommentSummary:o}=X();i.useEffect(()=>{if(!a)return;let r=!1;return zo(t).then(l=>{r||o(t,l)}).catch(l=>console.error(`Comment counts of "${t}" could not be loaded: ${l.message}`)),()=>{r=!0}},[t,s,n,a])}function Fi(t){const{commentSummary:s,currentProject:n}=X();return!t||s.project!==n?null:s.docs[t]??null}function Ka(){const[t,s]=i.useState(!1);return{copied:t,copy:async a=>{await navigator.clipboard.writeText(a),s(!0),setTimeout(()=>s(!1),2e3)}}}function Ja(t){const{publicationsVersion:s}=X(),[n,a]=i.useState(null),[o,r]=i.useState(null),[l,c]=i.useState(0);i.useEffect(()=>{let u=!1;return Fo(t).then(m=>{u||(a({project:t,publications:m}),r(null))}).catch(m=>{u||r(m.message)}),()=>{u=!0}},[t,s,l]);const d=i.useCallback(()=>c(u=>u+1),[]);return{publications:n?.project===t?n.publications:null,error:o,reload:d}}function Oi({project:t,doc:s,latestVersion:n,readOnly:a}){const{publications:o,reload:r}=Ja(t),[l,c]=i.useState(!1),d=o?.find(m=>m.docId===s.id)??null;if(i.useEffect(()=>{if(!l)return;const m=h=>{h.key==="Escape"&&c(!1)};return window.addEventListener("keydown",m),()=>window.removeEventListener("keydown",m)},[l]),o===null||!d&&a)return null;const u=()=>{l||r(),c(!l)};return e.jsxs("div",{className:"menu-anchor",children:[e.jsxs("button",{className:`btn-secondary publish-btn${l?" publish-btn--open":""}`,onClick:u,title:d?"Public link of this document":"Publish this document",children:[e.jsx(Mt,{size:14,className:d?"publish-btn-icon--published":void 0}),d?"Published":"Publish",d?.status==="modified"&&e.jsx("span",{className:"publish-btn-dot",title:"Changed since it was published"})]}),l&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"menu-backdrop",onClick:()=>c(!1)}),e.jsx("div",{className:"publish-popover",role:"dialog","aria-label":d?"Document published":"Publish this document",children:d?e.jsx(Hi,{publication:d,readOnly:a,onClose:()=>c(!1),onChanged:r}):e.jsx(Ui,{project:t,doc:s,latestVersion:n,onClose:()=>c(!1),onChanged:r})})]})]})}function Ya({title:t,published:s,onClose:n}){return e.jsxs("div",{className:"publish-head",children:[s&&e.jsx("span",{className:"publish-online-dot"}),e.jsx("span",{className:"publish-title",children:t}),e.jsx("button",{className:"publish-close",onClick:n,"aria-label":"Close",children:e.jsx(pn,{size:14})})]})}function Xa({label:t,value:s,onChange:n,placeholder:a,multiline:o}){return e.jsxs("label",{className:"publish-field",children:[e.jsxs("span",{className:"publish-field-label",children:[t," ",e.jsx("span",{className:"publish-field-optional",children:"(optional)"})]}),o?e.jsx("textarea",{className:"publish-input publish-input--multiline",value:s,maxLength:ts,rows:3,placeholder:a,onChange:r=>n(r.target.value),autoFocus:!0}):e.jsx("input",{className:"publish-input",value:s,maxLength:ts,placeholder:a,onChange:r=>n(r.target.value)})]})}function Ui({project:t,doc:s,latestVersion:n,onClose:a,onChanged:o}){const[r,l]=i.useState(""),[c,d]=i.useState(!1),[u,m]=i.useState(null),h=async()=>{d(!0),m(null);try{await Oo(t,s.id,r),o()}catch(p){m(p instanceof Error?p.message:String(p))}finally{d(!1)}};return e.jsxs(e.Fragment,{children:[e.jsx(Ya,{title:"Publish this document",onClose:a}),e.jsx("p",{className:"publish-text",children:"The public link shows the current version, frozen. Later changes only appear there once the publication is updated."}),e.jsxs("div",{className:"publish-version",children:[e.jsx(Al,{size:14}),"Version ",Te(n)," · modified ",us(s.updatedAt)]}),e.jsx(Xa,{label:"Version note",value:r,onChange:l,placeholder:"e.g. First version shared with the infra team",multiline:!0}),e.jsxs("div",{className:"publish-access",children:[e.jsx(mn,{size:14}),"Anyone with the link can read this document."]}),u&&e.jsx("div",{className:"publish-error",children:u}),e.jsxs("div",{className:"publish-actions",children:[e.jsx("button",{className:"btn-secondary",onClick:a,disabled:c,children:"Cancel"}),e.jsxs("button",{className:"btn-primary",onClick:h,disabled:c,children:[e.jsx(Mt,{size:14}),c?"Publishing…":"Publish"]})]})]})}function Hi({publication:t,readOnly:s,onClose:n,onChanged:a}){const[o,r]=i.useState(""),[l,c]=i.useState(!1),[d,u]=i.useState(null),[m,h]=i.useState(!1),{copied:p,copy:f}=Ka(),k=hn(t.token),v=t.status==="modified",g=async y=>{c(!0),u(null);try{await y(),r(""),h(!1),a()}catch(N){u(N instanceof Error?N.message:String(N))}finally{c(!1)}};return e.jsxs(e.Fragment,{children:[e.jsx(Ya,{title:"Document published",published:!0,onClose:n}),e.jsxs("div",{className:"publish-link",children:[e.jsx(mn,{size:14,className:"publish-link-icon"}),e.jsx("span",{className:"publish-link-url",title:k,children:k}),e.jsx("a",{className:"publish-icon-btn",href:k,target:"_blank",rel:"noopener noreferrer",title:"Open the public page",children:e.jsx(na,{size:14})}),e.jsx("button",{className:"publish-copy-btn",onClick:()=>f(k),title:"Copy the link",children:p?e.jsx(Ee,{size:14}):e.jsx(Lt,{size:14})})]}),e.jsxs("div",{className:"publish-meta",children:["Published ",us(t.publishedAt)," · version ",Te(t.version)]}),t.note&&e.jsx("div",{className:"publish-quote",children:t.note}),e.jsx("div",{className:"publish-sep"}),v?e.jsxs("div",{className:"publish-warning",children:[e.jsx(Ns,{size:14}),e.jsxs("div",{children:["The document changed since it was published.",e.jsx("br",{}),"Published: ",Te(t.version)," · current: ",Te(t.currentVersion)]})]}):e.jsxs("div",{className:"publish-uptodate",children:[e.jsx(Xe,{size:14}),"The published version is up to date."]}),!s&&v&&!m&&e.jsx(Xa,{label:"Note for the new version",value:o,onChange:r,placeholder:"e.g. Added the Entry points section"}),d&&e.jsx("div",{className:"publish-error",children:d}),!s&&(m?e.jsx(Qa,{busy:l,onCancel:()=>h(!1),onConfirm:()=>g(()=>fn(t.id))}):e.jsxs("div",{className:"publish-actions publish-actions--split",children:[e.jsxs("button",{className:"btn-secondary publish-danger-btn",onClick:()=>h(!0),disabled:l,children:[e.jsx(ws,{size:14}),"Unpublish"]}),v&&e.jsxs("button",{className:"btn-primary",onClick:()=>g(()=>gn(t.id,o)),disabled:l,children:[e.jsx(Ct,{size:14}),l?"Updating…":"Update publication"]})]}))]})}function Qa({title:t,busy:s,onCancel:n,onConfirm:a}){return e.jsxs("div",{className:"publish-confirm",children:[e.jsx("div",{className:"publish-confirm-title",children:t?`Unpublish “${t}”?`:"Unpublish this document?"}),e.jsx("div",{className:"publish-confirm-text",children:"The link stops working immediately. Publishing again creates a new link."}),e.jsxs("div",{className:"publish-actions",children:[e.jsx("button",{className:"btn-secondary",onClick:n,disabled:s,children:"Cancel"}),e.jsx("button",{className:"publish-confirm-btn",onClick:a,disabled:s,children:s?"Unpublishing…":"Unpublish"})]})]})}function tn(t){return t.replace(/[^a-zA-Z0-9_\-. ]/g,"_")}const Bi=1280,ls="mcp-documentor.contextRail",Ze=()=>typeof window>"u"||window.innerWidth>=Bi;function Wi(){try{const t=JSON.parse(localStorage.getItem(ls)??"null");return t&&t.wide===Ze()?t.open:null}catch{return null}}function Zt(t){try{t===null?localStorage.removeItem(ls):localStorage.setItem(ls,JSON.stringify({open:t,wide:Ze()}))}catch{}}function sn(t){if(!t)return"the last snapshot";const s=new Date(t);if(Number.isNaN(s.getTime()))return"the last snapshot";const n=a=>String(a).padStart(2,"0");return`${s.toLocaleDateString(void 0,{month:"short",day:"numeric",year:"numeric"})} ${n(s.getHours())}:${n(s.getMinutes())}`}function Vi(){const t=re(),s=X(),{selectedDoc:n,selectedDocId:a,freshnessResult:o,setFreshnessResult:r,setSelectedDoc:l,setDocs:c,docs:d,currentProject:u,projects:m,historyEntries:h,historyVersionContent:p,setHistoryEntries:f,setHistoryVersionContent:k,readOnly:v,codeSourcesVersion:g}=s,y=i.useRef(null),N=i.useRef(null),j=i.useRef(null),[b,E]=i.useState("document"),[D,$]=i.useState(null),[w,S]=i.useState(!1),[I,x]=i.useState(!1),[P,F]=i.useState(!1),[B,W]=i.useState(!1),[G,L]=i.useState(!1),[q,T]=i.useState(""),[V,Y]=i.useState(!1),[be,ue]=i.useState(null),[Ue,ye]=i.useState(!1),[$e,Ne]=i.useState(null),[ot,Re]=i.useState(null),[He,te]=i.useState(!1),[pe,he]=i.useState(!1),[Pe,De]=i.useState(!1),[Me,we]=i.useState(null),[M,U]=i.useState(!1),[K,J]=i.useState(!1),[fe,At]=i.useState([]),[ho,_t]=i.useState(null),[Ss,Be]=i.useState(()=>Wi()??Ze()),[mo,We]=i.useState("page"),[ge,po]=i.useState(null),[zt,Ft]=i.useState(null),[Ot,rt]=i.useState(null),Es=i.useRef(null),Ut=C=>{Zt(C),Be(C)},$s=b==="diff",Rs=b==="history";i.useEffect(()=>{window.__pdfReady=!!(n&&!G)},[n,G]),i.useEffect(()=>{let C=Ze();const R=()=>{const _=Ze();_!==C&&(C=_,Zt(null),Be(_))};return window.addEventListener("resize",R),()=>window.removeEventListener("resize",R)},[]),i.useEffect(()=>{const C=R=>{(R.metaKey||R.ctrlKey)&&R.key==="\\"&&(R.preventDefault(),Be(_=>(Zt(!_),!_)))};return window.addEventListener("keydown",C),()=>window.removeEventListener("keydown",C)},[]),i.useEffect(()=>{if(!a)return;window.__pdfReady=!1,window.__mermaidPending=0,y.current&&(y.current.scrollTop=0),E("document"),$(null),F(!1),f(null),L(!1),ue(null),Ne(null),he(!1),we(null),U(!1),J(!1),At([]),_t(null),We("page"),Ft(null),rt(null);const C=xe(a),R=new AbortController;let _=!1;const H=encodeURIComponent(u);return fetch(`/api/doc/${C}?project=${H}`,{signal:R.signal}).then(z=>z.json()).then(z=>{_||(z.doc?l(z.doc):F(!0))}).catch(z=>{_||z.name==="AbortError"||F(!0)}),fetch(`/api/freshness/${C}?project=${H}`,{signal:R.signal}).then(z=>z.json()).then(z=>{_||!z.report||r(z.report)}).catch(()=>{}),fetch(`/api/history/${C}?project=${H}`,{signal:R.signal}).then(z=>z.json()).then(z=>{_||f(z.versions??[])}).catch(()=>{}),()=>{_=!0,R.abort()}},[a,u]),i.useEffect(()=>{if(g===0||!a)return;const C=new AbortController;return fetch(`/api/freshness/${xe(a)}?project=${encodeURIComponent(u)}`,{signal:C.signal}).then(R=>R.json()).then(R=>{R.report&&r(R.report)}).catch(()=>{}),()=>C.abort()},[g]),i.useEffect(()=>{if(b!=="document"||G||!n){At([]);return}const C=requestAnimationFrame(()=>{const R=y.current?.querySelector(".doc-content");if(!R)return;const _=[...R.querySelectorAll("h1, h2, h3")];At(_.filter(H=>H.id).map(H=>({id:H.id,text:H.textContent??"",level:Number(H.tagName.slice(1))})))});return()=>cancelAnimationFrame(C)},[n,b,G]),i.useEffect(()=>{const C=y.current;if(!C||fe.length===0)return;const R=()=>{const _=C.getBoundingClientRect().top+80;let H=fe[0].id;for(const z of fe){const se=document.getElementById(z.id);se&&se.getBoundingClientRect().top<=_&&(H=z.id)}_t(H)};return R(),C.addEventListener("scroll",R,{passive:!0}),()=>C.removeEventListener("scroll",R)},[fe]);const fo=i.useCallback(C=>{document.getElementById(C)?.scrollIntoView({behavior:"smooth",block:"start"}),_t(C)},[]),Ce=_i(u,n?.id),ke=Fi(n?.id),lt=Uo(ge),go=i.useMemo(()=>(Ce.data?.comments??[]).filter(C=>!C.parentId&&!C.detached),[Ce.data]),me=Ho(lt,go),xo=(Ce.data?.comments??[]).filter(C=>!C.read).length;i.useEffect(()=>{const C=Ce.data;!n||!C||Es.current===n.id||(Es.current=n.id,C.comments.some(R=>!R.read)&&(We("comments"),Be(!0)))},[Ce.data,n]),i.useEffect(()=>{ut("dc-passage",[...me.values()].map(_=>_.range));const C=Ot??zt,R=C?me.get(C):void 0;ut("dc-focus",R?[R.range]:[])},[me,Ot,zt]),i.useEffect(()=>()=>{ut("dc-passage",[]),ut("dc-focus",[])},[]);const Ht=i.useCallback((C,R)=>{if(!lt)return null;const _=Bo(C,R),H=_?lt.indexAt(_.node,_.offset):null;if(H===null)return null;for(const[z,se]of me)if(H>=se.start&&H<se.end)return z;return null},[lt,me]);i.useEffect(()=>{if(!ge||me.size===0)return;const C=z=>{if(!window.getSelection()?.isCollapsed||z.target.closest("a, button"))return;const se=Ht(z.clientX,z.clientY);se&&(Ft(se),We("comments"),Be(!0))};let R=0;const _=z=>{cancelAnimationFrame(R),R=requestAnimationFrame(()=>rt(Ht(z.clientX,z.clientY)))},H=()=>{cancelAnimationFrame(R),rt(null)};return ge.addEventListener("click",C),ge.addEventListener("mousemove",_),ge.addEventListener("mouseleave",H),()=>{cancelAnimationFrame(R),ge.removeEventListener("click",C),ge.removeEventListener("mousemove",_),ge.removeEventListener("mouseleave",H)}},[ge,me,Ht]);const vo=i.useCallback(C=>{Ft(C),me.get(C)?.range.startContainer.parentElement?.scrollIntoView({behavior:"smooth",block:"center"})},[me]),Bt=i.useMemo(()=>({code:Wo,a({href:C,children:R,..._}){if(C?.startsWith("doc://")){const H=ql(C.slice(6)),z=H.indexOf(":");if(z!==-1){const ae=H.slice(0,z),Ge=H.slice(z+1),Ke=m.includes(ae);return e.jsx("button",{className:Ke?"doc-inline-link doc-inline-link--cross-project":"doc-inline-link doc-inline-link--broken",onClick:()=>{Ke&&t(ne(ae,Ge))},title:Ke?`Projet : ${ae}`:`Projet introuvable : ${ae}`,children:R})}const se=H,qe=d.some(ae=>ae.id===se);return e.jsx("button",{className:qe?"doc-inline-link":"doc-inline-link doc-inline-link--broken",onClick:()=>{qe&&t(ne(u,se))},title:qe?void 0:`Document introuvable : ${se}`,children:R})}return C?.startsWith("#")?e.jsx("a",{href:C,onClick:H=>{H.preventDefault(),document.getElementById(C.slice(1))?.scrollIntoView({behavior:"smooth"})},..._,children:R}):e.jsx("a",{href:C,target:"_blank",rel:"noopener noreferrer",..._,children:R})},img({src:C,alt:R,..._}){return e.jsx("img",{src:C,alt:R??"",className:"doc-image",..._})}}),[d,m,u,t]),jo=i.useMemo(()=>n&&e.jsx(cn,{remarkPlugins:[un],rehypePlugins:[dn],components:Bt,urlTransform:C=>C.startsWith("doc://")?C:Vo(C),children:n.content}),[n,Bt]);if(!n&&!a)return e.jsx("div",{className:"doc-viewer",children:e.jsx("div",{className:"doc-viewer-empty",children:"Select a documentation entry to view"})});if(a&&P&&!n)return e.jsx("div",{className:"doc-viewer",children:e.jsx("div",{className:"doc-viewer-empty",children:"No documentation at this path in the current project."})});const bo=async()=>{if(n)try{const R=await(await fetch(`/api/freshness/${xe(n.id)}?project=${encodeURIComponent(u)}`)).json();R.report&&r(R.report)}catch{}},yo=async()=>{n&&(await navigator.clipboard.writeText(n.content),x(!0),setTimeout(()=>x(!1),2e3))},No=()=>{if(!n)return;const C=new Blob([n.content],{type:"text/markdown;charset=utf-8"}),R=URL.createObjectURL(C),_=document.createElement("a");_.href=R,_.download=`${tn(n.title)}.md`,document.body.appendChild(_),_.click(),document.body.removeChild(_),URL.revokeObjectURL(R)},wo=async()=>{if(!n)return;const C=Number(localStorage.getItem("printScale")??100)/100,R=u,_=n.id;ye(!0),Ne(null);try{const H=new URLSearchParams({project:R,docId:_,scale:String(C)}),z=await fetch(`/api/pdf?${H}`);if(z.status===503){const Ge=await z.json();Ne(Ge.message??"Navigateur introuvable pour la génération PDF."),setTimeout(()=>Ne(null),8e3);return}if(!z.ok){Ne("Échec de la génération PDF."),setTimeout(()=>Ne(null),5e3);return}const se=await z.blob(),qe=await new Promise((Ge,Ke)=>{const dt=new FileReader;dt.onload=()=>Ge(dt.result),dt.onerror=Ke,dt.readAsDataURL(se)}),ae=document.createElement("a");ae.href=qe,ae.download=`${tn(n.title)}.pdf`,document.body.appendChild(ae),ae.click(),document.body.removeChild(ae)}finally{ye(!1)}},Co=async()=>{if(!(!n||h!==null)){W(!0);try{const R=await(await fetch(`/api/history/${xe(n.id)}?project=${encodeURIComponent(u)}`)).json();f(R.versions??[])}catch{f([])}finally{W(!1)}}},ko=async()=>{if(!(!n||D!==null)){S(!0);try{const R=await(await fetch(`/api/git-diff/${xe(n.id)}?project=${encodeURIComponent(u)}`)).json();$(R.diff??R.error??"No diff available.")}catch{$("Failed to load diff.")}finally{S(!1)}}},Ve=C=>{E(C),U(!1),J(!1),C!=="document"&&L(!1),C==="diff"&&ko(),C==="history"&&Co()},So=C=>{const R=N.current;if(!R)return;const _=R.selectionStart,H=R.selectionEnd,z=q.slice(0,_)+C+q.slice(H);T(z),requestAnimationFrame(()=>{R.selectionStart=R.selectionEnd=_+C.length,R.focus()})},Eo=async()=>{if(n){Y(!0),ue(null);try{const C=xe(n.id),R=await fetch(`/api/doc/${C}?project=${encodeURIComponent(u)}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:q})}),_=await R.json();if(!R.ok||_.error)throw new Error(_.error||"Save failed");const H=new Date().toISOString();l({...n,content:q,updatedAt:H}),c(d.map(z=>z.id===n.id?{...z,updatedAt:H}:z)),L(!1)}catch(C){ue(C instanceof Error?C.message:"Save failed")}finally{Y(!1)}}},$o=async()=>{if(n){De(!0),we(null);try{const C=xe(n.id),R=await fetch(`/api/doc/${C}?project=${encodeURIComponent(u)}`,{method:"DELETE"}),_=await R.json();if(!R.ok||_.error)throw new Error(_.error||"Delete failed");const H=n.id;c(d.filter(z=>z.id!==H)),l(null),r(null),he(!1),t(ne(u,null),{replace:!0})}catch(C){we(C instanceof Error?C.message:"Delete failed")}finally{De(!1)}}},Wt=n?d.find(C=>C.id===n.id):void 0,Ps=Wt?.isStale??!1,Le=n?.tracked_files.length??0,it=o?.modified.length??0,ct=h&&h.length>0?h[0].version:null,Ds=n&&Le>0?n.tracked_files.map(C=>C.lastModifiedAt).filter(Boolean).sort().slice(-1)[0]:void 0,Ro=[...Wt?.folder?Wt.folder.split("/").filter(Boolean):[],n?.title??"…"],Po=!v&&!!n&&b==="document";return e.jsxs("div",{className:"doc-viewer",children:[e.jsxs("div",{className:"doc-main",ref:y,children:[e.jsxs("div",{className:"doc-topbar",children:[e.jsxs("div",{className:"doc-topbar-left",children:[e.jsxs("div",{className:"doc-breadcrumb",children:[e.jsx("button",{className:"nav-btn",onClick:()=>t(-1),title:"Go back",children:"←"}),e.jsx("button",{className:"nav-btn",onClick:()=>t(1),title:"Go forward",children:"→"}),Ro.map((C,R)=>e.jsxs("span",{className:"doc-breadcrumb-segment",children:[R>0&&e.jsx("span",{className:"doc-breadcrumb-sep",children:"/"}),C]},`${C}-${R}`))]}),e.jsx("h1",{className:"doc-title",children:n?.title??"…"})]}),e.jsxs("div",{className:"doc-actions",children:[!Ss&&n&&e.jsx("button",{className:"icon-btn",onClick:()=>Ut(!0),title:"Show details (Ctrl/⌘ + \\)",children:"|◁"}),n&&!G&&ke&&ke.total>0&&e.jsxs("button",{className:"btn-secondary doc-comments-btn",onClick:()=>{We("comments"),Ut(!0)},title:ke.unread>0?`${ke.total} comments, ${ke.unread} unread`:`${ke.total} comments`,children:[e.jsx(ds,{size:13}),ke.total,ke.unread>0&&e.jsx("span",{className:"doc-comments-dot"})]}),n&&!G&&e.jsx(Oi,{project:u,doc:n,latestVersion:ct,readOnly:v},n.id),Po&&e.jsx("button",{className:`btn-primary${G?" active":""}`,onClick:()=>{!G&&n&&T(n.content),L(!G),ue(null)},title:G?"Cancel editing":"Edit document",children:G?"✕ Cancel":"✎ Edit"}),n&&!G&&e.jsxs("div",{className:"menu-anchor",children:[e.jsx("button",{className:"btn-secondary",onClick:()=>{U(C=>!C),J(!1)},title:"Export this document",children:"↓ Export ▾"}),M&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"menu-backdrop",onClick:()=>U(!1)}),e.jsxs("div",{className:"menu-popover",children:[e.jsx("button",{className:"menu-item",onClick:()=>{U(!1),yo()},children:I?"✓ Copied!":"⎘ Copy markdown"}),e.jsx("button",{className:"menu-item",onClick:()=>{U(!1),No()},children:"↓ Download .md"}),e.jsx("button",{className:"menu-item",disabled:Ue,onClick:()=>{U(!1),wo()},children:Ue?"⏳ PDF…":"↓ Download PDF"})]})]})]}),n&&!G&&e.jsxs("div",{className:"menu-anchor",children:[e.jsx("button",{className:"btn-icon-secondary",onClick:()=>{J(C=>!C),U(!1)},title:"More actions",children:"⋯"}),K&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"menu-backdrop",onClick:()=>J(!1)}),e.jsxs("div",{className:"menu-popover menu-popover--right",children:[Le>0&&e.jsx("button",{className:"menu-item",onClick:()=>{J(!1),bo()},children:"⟳ Re-check freshness"}),e.jsx("button",{className:"menu-item",onClick:()=>{J(!1),navigator.clipboard.writeText(n.id)},children:"⎘ Copy doc ID"}),!v&&e.jsx("button",{className:"menu-item menu-item--danger",onClick:()=>{J(!1),we(null),he(!0)},children:"🗑 Delete document"})]})]})]})]})]}),e.jsxs("nav",{className:"doc-tabs",children:[e.jsx("button",{className:`doc-tab${b==="document"?" active":""}`,onClick:()=>Ve("document"),children:"Document"}),Le>0&&e.jsx("button",{className:`doc-tab${$s?" active":""}`,onClick:()=>Ve("diff"),children:w?"Diff…":`Diff${it>0?` · ${it}`:""}`}),e.jsx("button",{className:`doc-tab${Rs?" active":""}`,onClick:()=>Ve("history"),children:B?"History…":`History${ct!==null?` · v${ct}`:""}`}),Le>0&&e.jsxs("button",{className:`doc-tab${b==="files"?" active":""}`,onClick:()=>Ve("files"),children:["Tracked files · ",Le]})]}),$e&&e.jsx("div",{className:"pdf-error-banner",children:$e}),b==="document"&&!G&&Ps&&Le>0&&e.jsxs("div",{className:"stale-banner",children:[e.jsx("span",{className:"stale-banner-icon",children:"⚠"}),e.jsxs("div",{className:"stale-banner-body",children:[e.jsx("span",{className:"stale-banner-text",children:it>0?`${it} of ${Le} tracked files changed since the snapshot taken on ${sn(Ds)}.`:`Tracked files changed since the snapshot taken on ${sn(Ds)}.`}),e.jsx("button",{className:"stale-banner-link",onClick:()=>Ve("diff"),children:"View diff"})]})]}),b==="files"&&n&&(o?e.jsx(pi,{report:o,trackedFiles:n.tracked_files,docId:n.id,onViewCode:Re}):e.jsx("div",{className:"doc-tab-loading",children:"Checking tracked files…"})),Rs&&n&&e.jsx($i,{docId:n.id,project:u,entries:h??[],selectedVersion:p,onSelectVersion:async C=>{const _=await(await fetch(`/api/history-version/${xe(n.id)}/${C}?project=${encodeURIComponent(u)}`)).json();k(_??null)},markdownComponents:Bt}),$s&&(w&&D===null?e.jsx("div",{className:"doc-tab-loading",children:"Loading diff…"}):e.jsx(xi,{diffText:D??""})),b==="document"&&(G&&n?e.jsxs("div",{className:"doc-editor",children:[e.jsx("textarea",{ref:N,className:"doc-editor-textarea",value:q,onChange:C=>T(C.target.value),spellCheck:!1}),e.jsxs("div",{className:"doc-editor-actions",children:[be&&e.jsx("span",{className:"doc-editor-error",children:be}),e.jsxs("div",{className:"doc-editor-actions-right",children:[e.jsx("button",{ref:j,type:"button",className:"image-insert-trigger-btn",onClick:()=>te(C=>!C),title:"Insert image",children:"🖼 Image"}),He&&e.jsx(Li,{project:u,triggerRef:j,onInsert:So,onClose:()=>te(!1)}),e.jsx("button",{type:"button",className:"save-btn",onClick:Eo,disabled:V,children:V?"Saving…":"✓ Save"})]})]})]}):e.jsx("div",{className:"doc-content",ref:po,children:jo}))]}),Ss&&n&&e.jsx(Mi,{doc:n,isStale:Ps,report:o,toc:fe,activeHeadingId:ho,version:ct,onSelectHeading:fo,onSelectFile:Re,onClose:()=>Ut(!1),tab:mo,onTab:We,unreadComments:xo,comments:Ce.data?.publication?e.jsx(Ai,{data:Ce.data,locatedIds:new Set(me.keys()),activeId:zt,hoveredId:Ot,readOnly:v,onActivate:C=>{b!=="document"&&E("document"),vo(C)},onHover:rt,onDelete:Ce.remove},n.id):null}),pe&&n&&e.jsx("div",{className:"modal-overlay",onClick:()=>!Pe&&he(!1),children:e.jsxs("div",{className:"modal-content delete-modal",onClick:C=>C.stopPropagation(),children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("span",{className:"modal-title",children:"Delete documentation"}),e.jsx("button",{className:"modal-close-btn",onClick:()=>he(!1),disabled:Pe,children:"✕"})]}),e.jsxs("div",{className:"modal-body",children:[e.jsxs("p",{className:"delete-modal-text",children:["Delete ",e.jsx("strong",{children:n.title})," (",e.jsx("code",{children:n.id}),") from project"," ",e.jsx("strong",{children:u}),"? This action cannot be undone from the interface."]}),Me&&e.jsx("span",{className:"doc-editor-error",children:Me}),e.jsxs("div",{className:"delete-modal-actions",children:[e.jsx("button",{type:"button",className:"copy-btn",onClick:()=>he(!1),disabled:Pe,children:"Cancel"}),e.jsx("button",{type:"button",className:"delete-btn delete-btn--confirm",onClick:$o,disabled:Pe,children:Pe?"Deleting…":"🗑 Delete"})]})]})]})}),ot&&n&&e.jsx(Di,{docId:n.id,project:u,filePath:ot,onClose:()=>Re(null)})]})}async function ks(t,s){const n=await fetch(t,s);let a=null;try{a=await n.json()}catch{}if(!n.ok)throw new Error(a?.error??`HTTP ${n.status}`);return a}function qi(){return ks("/api/logs")}function Gi(t,s){const n=s?`?knownSize=${s.size}&knownMtime=${encodeURIComponent(s.mtime??"")}`:"";return ks(`/api/logs/${t}${n}`)}function Ki(){return ks("/api/logs/open-folder",{method:"POST"})}const Ji=t=>`/api/logs/${t}/download`;function et(t){return t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(t<10*1024?1:0)} KB`:`${(t/(1024*1024)).toFixed(1)} MB`}function ee(t){return t.toLocaleString("fr-FR")}function Za(t,s){return t.getFullYear()===s.getFullYear()&&t.getMonth()===s.getMonth()&&t.getDate()===s.getDate()}function It(t){return Za(new Date(t),new Date)}function eo(t){const s=new Date(t);if(Number.isNaN(s.getTime()))return t;const n=(o,r=2)=>String(o).padStart(r,"0"),a=`${n(s.getHours())}:${n(s.getMinutes())}:${n(s.getSeconds())}.${n(s.getMilliseconds(),3)}`;return Za(s,new Date)?a:`${n(s.getDate())}/${n(s.getMonth()+1)} ${a.slice(0,8)}`}function ft(t){return`${ee(t)} ms`}const to={hour:"Last hour",today:"Today",day:"Last 24 hours",week:"Last 7 days",all:"All loaded"};function so(t,s){if(s==="all")return!0;if(s==="today")return It(t);const n=Date.now()-new Date(t).getTime(),a=s==="hour"?36e5:s==="day"?864e5:7*864e5;return n<=a}const Yi=3e3;function no(t,s,n){i.useEffect(()=>{if(!s||(t(),!n))return;const a=setInterval(t,Yi);return()=>clearInterval(a)},[s,n,t])}function is(t,s,n){const[a,o]=i.useState(null),[r,l]=i.useState(null),[c,d]=i.useState(null),u=i.useRef(void 0),m=i.useRef(!1),h=i.useCallback(async()=>{if(!m.current){m.current=!0;try{const p=await Gi(t,u.current);"unchanged"in p||(u.current=p.file,o(p)),l(null),d(Date.now())}catch(p){l(p instanceof Error?p.message:String(p))}finally{m.current=!1}}},[t]);return no(h,s,n),{data:a,error:r,checkedAt:c}}function Xi(t){const[s,n]=i.useState(null),[a,o]=i.useState(null),r=i.useCallback(async()=>{try{n(await qi()),o(null)}catch(l){o(l instanceof Error?l.message:String(l))}},[]);return no(r,!0,t),{directory:s,error:a}}function Qi(t=1e3){const[s,n]=i.useState(()=>Date.now());return i.useEffect(()=>{const a=setInterval(()=>n(Date.now()),t);return()=>clearInterval(a)},[t]),s}function Zi(){const{syncEnabled:t,readOnly:s,currentProject:n}=X(),[a,o]=i.useState(null),[r,l]=i.useState(!1),[c,d]=i.useState(null),u=i.useCallback(async()=>{try{const v=await fetch("/api/sync/status"),g=await v.json();o(v.ok&&!g.error?g:null)}catch{o(null)}},[]);if(i.useEffect(()=>{!t||s||u()},[t,s,n,u]),!t||s)return null;const m=async()=>{if(!r){l(!0),d(null);try{const v=await fetch("/api/sync",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({})}),g=await v.json();!v.ok||g.error?d({ok:!1,message:g.error??`HTTP ${v.status}`}):d({ok:!0,message:g.message??"Sync terminée."})}catch(v){d({ok:!1,message:v?.message??"Sync failed"})}finally{l(!1),u()}}},h=[];a?.ahead&&h.push(`↑${a.ahead}`),a?.behind&&h.push(`↓${a.behind}`),a?.dirty?.length&&h.push(`●${a.dirty.length}`);const p=a?.conflicted?.length??0,f=r?"Sync…":p>0?`Conflits à résoudre (${p} fichier(s))`:["Sync",a?.branch,...h.length>0?[h.join(" ")]:[]].filter(Boolean).join(" · "),k=p>0?"!":h[0];return e.jsxs("div",{className:"sync-button-wrapper",children:[e.jsxs("button",{className:`rail-btn${p>0?" conflict":""}`,onClick:m,disabled:r,"data-tooltip":f,"aria-label":f,children:[e.jsx(Ct,{size:20,className:r?"spinning":void 0}),k&&e.jsx("span",{className:`rail-badge rail-badge--${p>0?"danger":"accent"}`,children:k})]}),c&&e.jsxs("div",{className:`sync-result${c.ok?"":" error"}`,children:[e.jsx("pre",{children:c.message}),e.jsx("button",{className:"sync-result-close",onClick:()=>d(null),title:"Fermer",children:"✕"})]})]})}function Se({icon:t,label:s,active:n,onClick:a,children:o}){return e.jsxs("button",{className:`rail-btn${n?" active":""}`,onClick:a,"data-tooltip":s,"aria-label":s,children:[e.jsx(t,{size:20}),o]})}function ec({active:t,onSelect:s,onOpenSettings:n,onOpenProjectSettings:a}){const{docs:o,commentSummary:r,currentProject:l}=X(),c=o.filter(h=>h.isStale).length,d=r.project===l?Object.values(r.docs).reduce((h,p)=>h+p.unread,0):0,u=is("github",!0,!0),m=i.useMemo(()=>(u.data?.entries??[]).filter(h=>It(h.ts)&&!h.ok).length,[u.data]);return e.jsxs("nav",{className:"nav-rail",children:[e.jsx("div",{className:"rail-logo",title:"MCP Documentor",children:e.jsx(El,{size:18})}),e.jsx(Oa,{variant:"rail",onOpenSettings:a}),e.jsx("div",{className:"rail-sep"}),e.jsx(Se,{icon:Ml,label:"Documentation",active:t==="docs",onClick:()=>s("docs")}),e.jsx(Se,{icon:at,label:"Search ⌘K",active:t==="search",onClick:()=>s("search")}),e.jsx(Se,{icon:Ll,label:c>0?`Outdated · ${c}`:"Outdated",active:t==="outdated",onClick:()=>s("outdated"),children:c>0&&e.jsx("span",{className:"rail-badge rail-badge--warn",children:c})}),e.jsx(Se,{icon:Qn,label:"Recent",active:t==="recent",onClick:()=>s("recent")}),e.jsx(Se,{icon:Ul,label:"Export bundles",active:t==="exports",onClick:()=>s("exports")}),e.jsx(Se,{icon:Mt,label:d>0?`Publications · ${d} unread comments`:"Publications",active:t==="publications",onClick:()=>s("publications"),children:d>0&&e.jsx("span",{className:"rail-badge rail-badge--accent",children:d})}),e.jsx("div",{className:"rail-sep"}),e.jsx(Se,{icon:ka,label:m>0?`Logs · ${m} failed today`:"Logs",active:t==="logs",onClick:()=>s("logs"),children:m>0&&e.jsx("span",{className:"rail-dot"})}),e.jsx("div",{className:"rail-spacer"}),e.jsx(Zi,{}),e.jsx(Se,{icon:$a,label:"Settings",active:!1,onClick:n})]})}function tc({onClose:t,onShowMigrationReport:s}){const{readOnly:n,bumpCommentsVersion:a}=X(),[o,r]=i.useState(!1),[l,c]=i.useState(""),[d,u]=i.useState(null),[m,h]=i.useState(""),[p,f]=i.useState(null),[k,v]=i.useState(""),[g,y]=i.useState(""),[N,j]=i.useState("text-embedding-3-small"),[b,E]=i.useState(100);i.useEffect(()=>{const x=localStorage.getItem("printScale");x&&E(Number(x)),Fa().then(P=>r(!!P)).catch(()=>{}),oi().then(P=>h(P.default??"")).catch(()=>{}),qo().then(P=>c(String(P))).catch(P=>u({ok:!1,text:P.message})),fetch("/api/config").then(P=>P.json()).then(P=>{P.dataDir&&v(P.dataDir),P.model&&j(P.model)}).catch(()=>{})},[]);const D=async(x,P)=>{await fetch("/api/configurations/apply",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:x,value:P})})},$=async()=>{f(null);try{const{path:x}=await ri(m);h(x??""),f({ok:!0,text:x?"Saved":"Removed"})}catch(x){f({ok:!1,text:x.message})}},w=async()=>{u(null);try{const x=await Go(Number(l));c(String(x)),u({ok:!0,text:"Saved"}),a()}catch(x){u({ok:!1,text:x.message})}},S=()=>{localStorage.setItem("printScale",String(b))},I=async()=>{await D("MCP_DATA_DIR",k),g&&await D("MCP_DOCUMENTOR_OPENAI_API_KEY",g),await D("MCP_DOCUMENTOR_OPENAI_MODEL",N),t()};return e.jsx("div",{className:"settings-overlay",onClick:t,children:e.jsxs("div",{className:"settings-popover",onClick:x=>x.stopPropagation(),children:[e.jsx("h2",{className:"settings-title",children:"Settings"}),e.jsxs("div",{className:"settings-field",children:[e.jsx("label",{className:"settings-label",children:"Data Directory"}),e.jsx("input",{className:"settings-input",type:"text",value:k,onChange:x=>v(x.target.value),placeholder:"Leave empty for default"})]}),e.jsxs("div",{className:"settings-field",children:[e.jsx("label",{className:"settings-label",children:"OpenAI API Key"}),e.jsx("input",{className:"settings-input",type:"password",value:g,onChange:x=>y(x.target.value),placeholder:"sk-..."})]}),e.jsxs("div",{className:"settings-field",children:[e.jsx("label",{className:"settings-label",children:"Embedding Model"}),e.jsx("input",{className:"settings-input",type:"text",value:N,onChange:x=>j(x.target.value)})]}),e.jsxs("div",{className:"settings-field",children:[e.jsx("label",{className:"settings-label",children:"Print Scale (%)"}),e.jsxs("div",{style:{display:"flex",gap:"8px",alignItems:"center"},children:[e.jsx("input",{className:"settings-input",type:"number",min:30,max:150,value:b,onChange:x=>E(Number(x.target.value)),style:{width:"80px"}}),e.jsx("button",{className:"settings-save-btn",onClick:S,children:"Apply"})]})]}),e.jsxs("div",{className:"settings-field",children:[e.jsx("label",{className:"settings-label",children:"Default code root (this machine)"}),e.jsxs("div",{style:{display:"flex",gap:"8px",alignItems:"center"},children:[e.jsx("input",{className:"settings-input",type:"text",value:m,disabled:n,onChange:x=>h(x.target.value),placeholder:"Absolute path — used by projects without their own root"}),!n&&e.jsx("button",{className:"settings-save-btn",onClick:$,children:"Apply"})]}),p&&e.jsx("span",{className:`settings-hint${p.ok?"":" error"}`,children:p.text})]}),e.jsxs("div",{className:"settings-field",children:[e.jsx("label",{className:"settings-label",children:"Comments per published document"}),e.jsxs("div",{style:{display:"flex",gap:"8px",alignItems:"center"},children:[e.jsx("input",{className:"settings-input",type:"number",min:1,max:500,value:l,disabled:n,onChange:x=>c(x.target.value),style:{width:"80px"}}),!n&&e.jsx("button",{className:"settings-save-btn",onClick:w,children:"Apply"})]}),e.jsx("span",{className:"settings-hint",children:"Replies included. A document already above the limit keeps its comments and accepts no new one."}),d&&e.jsx("span",{className:`settings-hint${d.ok?"":" error"}`,children:d.text})]}),o&&e.jsxs("div",{className:"settings-field",children:[e.jsx("label",{className:"settings-label",children:"Code sources"}),e.jsx("button",{className:"settings-link-btn",onClick:s,children:"View the environment variables migration report"})]}),e.jsxs("div",{className:"settings-actions",children:[e.jsx("button",{className:"settings-cancel-btn",onClick:t,children:"Cancel"}),!n&&e.jsx("button",{className:"settings-save-btn",onClick:I,children:"Save"})]})]})})}function sc({value:t,onChange:s,options:n}){const[a,o]=i.useState(!1),[r,l]=i.useState(-1),c=i.useRef(null),d=i.useMemo(()=>{const h=t.trim().toLowerCase();return h?n.filter(p=>p.toLowerCase().includes(h)):n},[n,t]);i.useEffect(()=>{if(!a)return;const h=p=>{c.current&&!c.current.contains(p.target)&&o(!1)};return document.addEventListener("mousedown",h),()=>document.removeEventListener("mousedown",h)},[a]),i.useEffect(()=>{l(-1)},[t,a]);const u=h=>{s(h),o(!1)},m=h=>{h.key==="ArrowDown"?(h.preventDefault(),a||o(!0),l(p=>Math.min(p+1,d.length-1))):h.key==="ArrowUp"?(h.preventDefault(),l(p=>Math.max(p-1,0))):h.key==="Enter"&&a&&r>=0&&d[r]?(h.preventDefault(),u(d[r])):h.key==="Escape"&&o(!1)};return e.jsxs("div",{className:"folder-combobox",ref:c,children:[e.jsx("input",{className:"settings-input",value:t,onChange:h=>{s(h.target.value),a||o(!0)},onFocus:()=>o(!0),onKeyDown:m,placeholder:"optional, e.g. backend/auth or backend/auth/new-subfolder",autoComplete:"off",spellCheck:!1}),e.jsx("button",{type:"button",className:"folder-combobox-toggle",onClick:()=>o(h=>!h),tabIndex:-1,"aria-label":"Toggle folder list",children:"▾"}),a&&e.jsxs("div",{className:"folder-combobox-menu",children:[e.jsx("div",{className:"folder-combobox-header",children:"Existing folders"}),d.length===0?e.jsx("div",{className:"folder-combobox-empty",children:n.length===0?"No folder yet — type a path to create one.":"No match — will create a new folder."}):e.jsx("ul",{className:"folder-combobox-list",children:d.map((h,p)=>e.jsx("li",{className:`folder-combobox-item${p===r?" active":""}`,onMouseDown:f=>{f.preventDefault(),u(h)},onMouseEnter:()=>l(p),children:h},h))})]})]})}function nc({onClose:t}){const s=re(),{currentProject:n,projects:a,docs:o}=X(),[r,l]=i.useState(n),[c,d]=i.useState(""),[u,m]=i.useState(""),[h,p]=i.useState(""),[f,k]=i.useState(""),[v,g]=i.useState(!1),[y,N]=i.useState(null),[j,b]=i.useState(null),E=i.useMemo(()=>{const w=new Set;for(const S of o)if(S.folder){const I=S.folder.split("/").filter(Boolean);for(let x=1;x<=I.length;x++)w.add(I.slice(0,x).join("/"))}return Array.from(w).sort()},[o]);i.useEffect(()=>{if(r===n){b(null);return}let w=!1;return fetch(`/api/folders?project=${encodeURIComponent(r)}`).then(S=>S.json()).then(S=>{w||(Array.isArray(S?.folders)?b(S.folders):b([]))}).catch(()=>{w||b([])}),()=>{w=!0}},[r,n]);const D=r===n?E:j??[],$=async()=>{if(!c.trim()||!f.trim()){N("Title and content are required");return}g(!0),N(null);try{const w=h.split(",").map(x=>x.trim()).filter(Boolean),S=await fetch("/api/doc",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({title:c.trim(),content:f,folder:u.trim()||void 0,tags:w.length?w:void 0,project:r})}),I=await S.json();if(!S.ok||I.error)throw new Error(I.error||"Create failed");t(),I.id&&r===n&&s(ne(n,I.id))}catch(w){N(w instanceof Error?w.message:"Create failed")}finally{g(!1)}};return e.jsx("div",{className:"settings-overlay",onClick:t,children:e.jsxs("div",{className:"settings-popover create-doc-popover",onClick:w=>w.stopPropagation(),children:[e.jsx("h2",{className:"settings-title",children:"New document"}),e.jsxs("div",{className:"create-doc-grid",children:[e.jsxs("div",{className:"settings-field",children:[e.jsx("label",{className:"settings-label",children:"Project"}),e.jsx("select",{className:"settings-input",value:r,onChange:w=>l(w.target.value),children:a.map(w=>e.jsxs("option",{value:w,children:[w,w===n?" (current)":""]},w))})]}),e.jsxs("div",{className:"settings-field",children:[e.jsx("label",{className:"settings-label",children:"Title *"}),e.jsx("input",{className:"settings-input",value:c,onChange:w=>d(w.target.value)})]}),e.jsxs("div",{className:"settings-field",children:[e.jsx("label",{className:"settings-label",children:"Folder"}),e.jsx(sc,{value:u,onChange:m,options:D}),e.jsx("div",{className:"create-doc-hint",children:"Pick from the existing tree or type a new path to add a sub-folder."})]}),e.jsxs("div",{className:"settings-field",children:[e.jsx("label",{className:"settings-label",children:"Tags"}),e.jsx("input",{className:"settings-input",value:h,onChange:w=>p(w.target.value),placeholder:"comma, separated, tags"})]})]}),e.jsxs("div",{className:"settings-field create-doc-content-field",children:[e.jsx("label",{className:"settings-label",children:"Content *"}),e.jsx("textarea",{className:"doc-editor-textarea create-doc-textarea",value:f,onChange:w=>k(w.target.value),spellCheck:!1,placeholder:`# My new document
4
+ `).map(s=>({type:fi(s),content:s}))}function xi({diffText:t}){const s=gi(t);return e.jsx("div",{className:"diff-viewer",children:e.jsx("pre",{className:"diff-pre",children:s.map((n,a)=>e.jsx("div",{className:`diff-line diff-line--${n.type}`,children:e.jsx("span",{className:"diff-line-content",children:n.content||" "})},a))})})}class vi{diff(s,n,a={}){let o;typeof a=="function"?(o=a,a={}):"callback"in a&&(o=a.callback);const r=this.castInput(s,a),l=this.castInput(n,a),c=this.removeEmpty(this.tokenize(r,a)),d=this.removeEmpty(this.tokenize(l,a));return this.diffWithOptionsObj(c,d,a,o)}diffWithOptionsObj(s,n,a,o){var r;const l=N=>{if(N=this.postProcess(N,a),o){setTimeout(function(){o(N)},0);return}else return N},c=n.length,d=s.length;let u=1,m=c+d;a.maxEditLength!=null&&(m=Math.min(m,a.maxEditLength));const h=(r=a.timeout)!==null&&r!==void 0?r:1/0,p=Date.now()+h,f=[{oldPos:-1,lastComponent:void 0}];let k=this.extractCommon(f[0],n,s,0,a);if(f[0].oldPos+1>=d&&k+1>=c)return l(this.buildValues(f[0].lastComponent,n,s));let v=-1/0,g=1/0;const y=()=>{for(let N=Math.max(v,-u);N<=Math.min(g,u);N+=2){let j;const b=f[N-1],E=f[N+1];b&&(f[N-1]=void 0);let D=!1;if(E){const w=E.oldPos-N;D=E&&0<=w&&w<c}const $=b&&b.oldPos+1<d;if(!D&&!$){f[N]=void 0;continue}if(!$||D&&b.oldPos<E.oldPos?j=this.addToPath(E,!0,!1,0,a):j=this.addToPath(b,!1,!0,1,a),k=this.extractCommon(j,n,s,N,a),j.oldPos+1>=d&&k+1>=c)return l(this.buildValues(j.lastComponent,n,s))||!0;f[N]=j,j.oldPos+1>=d&&(g=Math.min(g,N-1)),k+1>=c&&(v=Math.max(v,N+1))}u++};if(o)(function N(){setTimeout(function(){if(u>m||Date.now()>p)return o(void 0);y()||N()},0)})();else for(;u<=m&&Date.now()<=p;){const N=y();if(N)return N}}addToPath(s,n,a,o,r){const l=s.lastComponent;return l&&!r.oneChangePerToken&&l.added===n&&l.removed===a?{oldPos:s.oldPos+o,lastComponent:{count:l.count+1,added:n,removed:a,previousComponent:l.previousComponent}}:{oldPos:s.oldPos+o,lastComponent:{count:1,added:n,removed:a,previousComponent:l}}}extractCommon(s,n,a,o,r){const l=n.length,c=a.length;let d=s.oldPos,u=d-o,m=0;for(;u+1<l&&d+1<c&&this.equals(a[d+1],n[u+1],r);)u++,d++,m++,r.oneChangePerToken&&(s.lastComponent={count:1,previousComponent:s.lastComponent,added:!1,removed:!1});return m&&!r.oneChangePerToken&&(s.lastComponent={count:m,previousComponent:s.lastComponent,added:!1,removed:!1}),s.oldPos=d,u}equals(s,n,a){return a.comparator?a.comparator(s,n):s===n||!!a.ignoreCase&&s.toLowerCase()===n.toLowerCase()}removeEmpty(s){const n=[];for(let a=0;a<s.length;a++)s[a]&&n.push(s[a]);return n}castInput(s,n){return s}tokenize(s,n){return Array.from(s)}join(s){return s.join("")}postProcess(s,n){return s}get useLongestToken(){return!1}buildValues(s,n,a){const o=[];let r;for(;s;)o.push(s),r=s.previousComponent,delete s.previousComponent,s=r;o.reverse();const l=o.length;let c=0,d=0,u=0;for(;c<l;c++){const m=o[c];if(m.removed)m.value=this.join(a.slice(u,u+m.count)),u+=m.count;else{if(!m.added&&this.useLongestToken){let h=n.slice(d,d+m.count);h=h.map(function(p,f){const k=a[u+f];return k.length>p.length?k:p}),m.value=this.join(h)}else m.value=this.join(n.slice(d,d+m.count));d+=m.count,m.added||(u+=m.count)}}return o}}function Js(t,s){let n;for(n=0;n<t.length&&n<s.length;n++)if(t[n]!=s[n])return t.slice(0,n);return t.slice(0,n)}function Ys(t,s){let n;if(!t||!s||t[t.length-1]!=s[s.length-1])return"";for(n=0;n<t.length&&n<s.length;n++)if(t[t.length-(n+1)]!=s[s.length-(n+1)])return t.slice(-n);return t.slice(-n)}function as(t,s,n){if(t.slice(0,s.length)!=s)throw Error(`string ${JSON.stringify(t)} doesn't start with prefix ${JSON.stringify(s)}; this is a bug`);return n+t.slice(s.length)}function os(t,s,n){if(!s)return t+n;if(t.slice(-s.length)!=s)throw Error(`string ${JSON.stringify(t)} doesn't end with suffix ${JSON.stringify(s)}; this is a bug`);return t.slice(0,-s.length)+n}function Ye(t,s){return as(t,s,"")}function mt(t,s){return os(t,s,"")}function Xs(t,s){return s.slice(0,ji(t,s))}function ji(t,s){let n=0;t.length>s.length&&(n=t.length-s.length);let a=s.length;t.length<s.length&&(a=t.length);const o=Array(a);let r=0;o[0]=0;for(let l=1;l<a;l++){for(s[l]==s[r]?o[l]=o[r]:o[l]=r;r>0&&s[l]!=s[r];)r=o[r];s[l]==s[r]&&r++}r=0;for(let l=n;l<t.length;l++){for(;r>0&&t[l]!=s[r];)r=o[r];t[l]==s[r]&&r++}return r}function Ga(t,s){const n=[];for(const a of Array.from(s.segment(t))){const o=a.segment;n.length&&/\s/.test(n[n.length-1])&&/\s/.test(o)?n[n.length-1]+=o:n.push(o)}return n}function rs(t,s){if(s)return Qe(t,s)[1];let n;for(n=t.length-1;n>=0&&t[n].match(/\s/);n--);return t.substring(n+1)}function Ie(t,s){if(s)return Qe(t,s)[0];const n=t.match(/^\s*/);return n?n[0]:""}function Qe(t,s){if(!s)return[Ie(t),rs(t)];if(s.resolvedOptions().granularity!="word")throw new Error('The segmenter passed must have a granularity of "word"');const n=Ga(t,s),a=n[0],o=n[n.length-1],r=/\s/.test(a)?a:"",l=/\s/.test(o)?o:"";return[r,l]}const Qs="a-zA-Z0-9_\\u{AD}\\u{C0}-\\u{D6}\\u{D8}-\\u{F6}\\u{F8}-\\u{2C6}\\u{2C8}-\\u{2D7}\\u{2DE}-\\u{2FF}\\u{1E00}-\\u{1EFF}",bi=new RegExp(`[${Qs}]+|\\s+|[^${Qs}]`,"ug");class yi extends vi{equals(s,n,a){return a.ignoreCase&&(s=s.toLowerCase(),n=n.toLowerCase()),s.trim()===n.trim()}tokenize(s,n={}){let a;if(n.intlSegmenter){const l=n.intlSegmenter;if(l.resolvedOptions().granularity!="word")throw new Error('The segmenter passed must have a granularity of "word"');a=Ga(s,l)}else a=s.match(bi)||[];const o=[];let r=null;return a.forEach(l=>{/\s/.test(l)?r==null?o.push(l):o.push(o.pop()+l):r!=null&&/\s/.test(r)?o[o.length-1]==r?o.push(o.pop()+l):o.push(r+l):o.push(l),r=l}),o}join(s){return s.map((n,a)=>a==0?n:n.replace(/^\s+/,"")).join("")}postProcess(s,n){if(!s||n.oneChangePerToken)return s;let a=null,o=null,r=null;return s.forEach(l=>{l.added?o=l:l.removed?r=l:((o||r)&&Zs(a,r,o,l,n.intlSegmenter),a=l,o=null,r=null)}),(o||r)&&Zs(a,r,o,null,n.intlSegmenter),s}}const Ni=new yi;function wi(t,s,n){return Ni.diff(t,s,n)}function Zs(t,s,n,a,o){if(s&&n){const[r,l]=Qe(s.value,o),[c,d]=Qe(n.value,o);if(t){const u=Js(r,c);t.value=os(t.value,c,u),s.value=Ye(s.value,u),n.value=Ye(n.value,u)}if(a){const u=Ys(l,d);a.value=as(a.value,d,u),s.value=mt(s.value,u),n.value=mt(n.value,u)}}else if(n){if(t){const r=Ie(n.value,o);n.value=n.value.substring(r.length)}if(a){const r=Ie(a.value,o);a.value=a.value.substring(r.length)}}else if(t&&a){const r=Ie(a.value,o),[l,c]=Qe(s.value,o),d=Js(r,l);s.value=Ye(s.value,d);const u=Ys(Ye(r,d),c);s.value=mt(s.value,u),a.value=as(a.value,r,u),t.value=os(t.value,r,r.slice(0,r.length-u.length))}else if(a){const r=Ie(a.value,o),l=rs(s.value,o),c=Xs(l,r);s.value=mt(s.value,c)}else if(t){const r=rs(t.value,o),l=Ie(s.value,o),c=Xs(r,l);s.value=Ye(s.value,c)}}const Yt={create:"Created",update:"Updated",patch:"Patched",delete:"Deleted",snapshot:"Snapshot"},Xt={create:"➕",update:"📝",patch:"🩹",delete:"🗑️",snapshot:"📸"};function Ci(t,s){const n={};t.title!==s.title&&(n.title={from:t.title,to:s.title});const a=s.tags.filter(f=>!t.tags.includes(f)),o=t.tags.filter(f=>!s.tags.includes(f));(a.length||o.length)&&(n.tags={added:a,removed:o});const r=t.tracked_files.map(f=>f.path),l=s.tracked_files.map(f=>f.path),c=l.filter(f=>!r.includes(f)),d=r.filter(f=>!l.includes(f));(c.length||d.length)&&(n.tracked_files={added:c,removed:d});const u=t.related_docs??[],m=s.related_docs??[],h=m.filter(f=>!u.includes(f)),p=u.filter(f=>!m.includes(f));return(h.length||p.length)&&(n.related_docs={added:h,removed:p}),n}function ki({diff:t}){return e.jsxs("div",{className:"history-meta-diff",children:[e.jsx("span",{className:"history-meta-diff-title",children:"Metadata changes"}),t.title&&e.jsxs("div",{className:"history-meta-diff-row",children:[e.jsx("span",{className:"history-meta-diff-field",children:"Title"}),e.jsx("span",{className:"history-meta-diff-chip--removed",children:t.title.from}),e.jsx("span",{className:"history-meta-diff-arrow",children:"→"}),e.jsx("span",{className:"history-meta-diff-chip--added",children:t.title.to})]}),t.tags&&e.jsxs("div",{className:"history-meta-diff-row",children:[e.jsx("span",{className:"history-meta-diff-field",children:"Tags"}),e.jsxs("div",{className:"history-meta-diff-chips",children:[t.tags.removed.map(s=>e.jsxs("span",{className:"history-meta-diff-chip--removed",children:["− ",s]},s)),t.tags.added.map(s=>e.jsxs("span",{className:"history-meta-diff-chip--added",children:["+ ",s]},s))]})]}),t.tracked_files&&e.jsxs("div",{className:"history-meta-diff-row",children:[e.jsx("span",{className:"history-meta-diff-field",children:"Tracked files"}),e.jsxs("div",{className:"history-meta-diff-chips",children:[t.tracked_files.removed.map(s=>e.jsxs("span",{className:"history-meta-diff-chip--removed",children:["− ",s]},s)),t.tracked_files.added.map(s=>e.jsxs("span",{className:"history-meta-diff-chip--added",children:["+ ",s]},s))]})]}),t.related_docs&&e.jsxs("div",{className:"history-meta-diff-row",children:[e.jsx("span",{className:"history-meta-diff-field",children:"Related docs"}),e.jsxs("div",{className:"history-meta-diff-chips",children:[t.related_docs.removed.map(s=>e.jsxs("span",{className:"history-meta-diff-chip--removed",children:["− ",s]},s)),t.related_docs.added.map(s=>e.jsxs("span",{className:"history-meta-diff-chip--added",children:["+ ",s]},s))]})]})]})}function Si({changes:t}){return e.jsx("div",{className:"history-inline-diff",children:t.map((s,n)=>s.added?e.jsx("span",{className:"history-inline-diff--added",children:s.value},n):s.removed?e.jsx("span",{className:"history-inline-diff--removed",children:s.value},n):e.jsx("span",{children:s.value},n))})}function Ei(t){const s=[],n=[];let a=null;for(const o of t)o.changeType==="snapshot"?(a={snapshot:o,subEntries:[]},n.push(a)):a===null?s.push(o):a.subEntries.push(o);return{uncommitted:s,groups:n}}function $i({docId:t,project:s,entries:n,selectedVersion:a,onSelectVersion:o,markdownComponents:r}){const[l,c]=i.useState(null),[d,u]=i.useState(!1),[m,h]=i.useState(new Set),{uncommitted:p,groups:f}=i.useMemo(()=>Ei(n),[n]),k=b=>{h(E=>{const D=new Set(E);return D.has(b)?D.delete(b):D.add(b),D})},v=a!==null&&(a.changeType==="update"||a.changeType==="patch"||a.changeType==="snapshot")&&a.version>1,g=(()=>{if(!a||!v)return null;if(a.changeType==="snapshot"){const b=n.filter(E=>E.version<a.version&&E.changeType==="snapshot").sort((E,D)=>D.version-E.version);return b.length>0?b[0].version:Math.min(...n.map(E=>E.version))}return a.version-1})(),y=g!==null?n.find(b=>b.version===g)??null:null,N=y?Ci(y.metadata,a.metadata):null,j=N&&Object.keys(N).length>0;return i.useEffect(()=>{if(c(null),!a||!v||g===null)return;let b=!1;return u(!0),fetch(`/api/history-version/${xe(t)}/${g}?project=${encodeURIComponent(s)}`).then(E=>E.json()).then(E=>{if(b)return;const D=E?.content??"",$=a.content??"";c(wi(D,$))}).catch(()=>{b||c([])}).finally(()=>{b||u(!1)}),()=>{b=!0}},[a?.version]),n.length===0?e.jsx("div",{className:"history-viewer",children:e.jsx("div",{className:"doc-viewer-empty",children:"No version history available for this document."})}):e.jsxs("div",{className:"history-viewer",children:[e.jsxs("div",{className:"history-list",children:[p.length>0&&e.jsxs("div",{className:"history-uncommitted",children:[e.jsx("span",{className:"history-uncommitted-label",children:"Non archivé"}),p.map(b=>{const E=a?.version===b.version,D=new Date(b.changedAt).toLocaleString(),$=Yt[b.changeType]??b.changeType,w=Xt[b.changeType]??"❓";return e.jsxs("button",{className:`history-entry history-entry--sub${E?" history-entry--active":""}`,onClick:()=>o(b.version),children:[e.jsxs("div",{className:"history-entry-header",children:[e.jsxs("span",{className:"history-entry-version",children:["v",b.version]}),e.jsxs("span",{className:`history-entry-type history-entry-type--${b.changeType}`,children:[w," ",$]})]}),e.jsx("span",{className:"history-entry-date",children:D})]},b.version)})]}),f.length===0&&p.length===0&&e.jsx("div",{className:"doc-viewer-empty",children:"No version history available."}),f.map(b=>{const E=a?.version===b.snapshot.version,D=m.has(b.snapshot.version),$=new Date(b.snapshot.changedAt).toLocaleString();return e.jsxs("div",{className:"history-group",children:[e.jsx("div",{className:`history-entry history-entry--snapshot-card${E?" history-entry--active":""}`,children:e.jsxs("button",{className:"history-entry-snapshot-main",onClick:()=>o(b.snapshot.version),children:[e.jsxs("div",{className:"history-entry-header",children:[e.jsxs("span",{className:"history-entry-version",children:["Version ",b.snapshot.version]}),e.jsx("span",{className:"history-entry-type history-entry-type--snapshot",children:"📸 Snapshot"})]}),e.jsxs("div",{className:"history-entry-footer",children:[e.jsx("span",{className:"history-entry-date",children:$}),b.subEntries.length>0&&e.jsx("span",{className:`history-group-toggle${D?" history-group-toggle--open":""}`,onClick:w=>{w.stopPropagation(),k(b.snapshot.version)},role:"button",tabIndex:0,onKeyDown:w=>{(w.key==="Enter"||w.key===" ")&&(w.stopPropagation(),k(b.snapshot.version))},children:D?"Masquer ▲":`Voir les ${b.subEntries.length} modification${b.subEntries.length>1?"s":""} ▼`})]})]})}),D&&e.jsx("div",{className:"history-group-entries",children:b.subEntries.map(w=>{const S=a?.version===w.version,I=new Date(w.changedAt).toLocaleString(),x=Yt[w.changeType]??w.changeType,P=Xt[w.changeType]??"❓";return e.jsxs("button",{className:`history-entry history-entry--sub${S?" history-entry--active":""}`,onClick:()=>o(w.version),children:[e.jsxs("div",{className:"history-entry-header",children:[e.jsxs("span",{className:"history-entry-version",children:["v",w.version]}),e.jsxs("span",{className:`history-entry-type history-entry-type--${w.changeType}`,children:[P," ",x]})]}),e.jsx("span",{className:"history-entry-date",children:I})]},w.version)})})]},b.snapshot.version)})]}),e.jsx("div",{className:"history-content",children:a?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"history-content-meta",children:[e.jsxs("div",{className:"history-content-meta-title",children:[e.jsx("strong",{children:a.metadata.title}),e.jsxs("span",{className:"history-content-version",children:["Version ",a.version]})]}),e.jsxs("div",{className:"history-content-meta-info",children:[e.jsxs("span",{className:`history-entry-type history-entry-type--${a.changeType}`,children:[Xt[a.changeType]??"❓"," ",Yt[a.changeType]??a.changeType]}),e.jsx("span",{className:"history-content-date",children:new Date(a.changedAt).toLocaleString()}),v&&d&&e.jsx("span",{className:"history-diff-loading",children:"Loading diff…"}),v&&!d&&g!==null&&e.jsxs("span",{className:"history-diff-base",children:["vs v",g]})]}),j&&e.jsx(ki,{diff:N})]}),v&&a.changeType==="snapshot"&&!d&&l!==null&&e.jsxs("div",{className:"history-diff-recap-banner",children:["Récapitulatif des modifications effectuées depuis le dernier évènement ",e.jsx("strong",{children:"snapshot"})]}),v?l!==null?e.jsx(Si,{changes:l}):null:e.jsx("div",{className:"doc-content",children:e.jsx(cn,{remarkPlugins:[un],rehypePlugins:[dn],components:r,children:a.content??""})})]}):e.jsx("div",{className:"doc-viewer-empty",children:"Select a version to view its content."})})]})}const Ri={ts:"typescript",tsx:"tsx",js:"javascript",jsx:"jsx",py:"python",rb:"ruby",go:"go",java:"java",rs:"rust",cs:"csharp",cpp:"cpp",c:"c",sh:"bash",bash:"bash",zsh:"bash",json:"json",yaml:"yaml",yml:"yaml",toml:"toml",md:"markdown",css:"css",scss:"scss",html:"html",xml:"xml",sql:"sql"};function Pi(t){const s=t.split(".").pop()?.toLowerCase()??"";return Ri[s]??"text"}function Di({docId:t,project:s,filePath:n,onClose:a}){const[o,r]=i.useState([]),[l,c]=i.useState(!0),[d,u]=i.useState(null);i.useEffect(()=>{const h=new AbortController,p=n.split("/").map(encodeURIComponent).join("/");return fetch(`/api/file-section/${p}?docId=${encodeURIComponent(t)}&project=${encodeURIComponent(s)}`,{signal:h.signal}).then(f=>f.json()).then(f=>{if(f.error)throw new Error(f.error);r(f.sections??[])}).catch(f=>{f.name!=="AbortError"&&u(f.message)}).finally(()=>c(!1)),()=>h.abort()},[t,n]),i.useEffect(()=>{const h=p=>{p.key==="Escape"&&a()};return document.addEventListener("keydown",h),()=>document.removeEventListener("keydown",h)},[a]);const m=Pi(n);return e.jsx("div",{className:"modal-overlay",onClick:a,children:e.jsxs("div",{className:"modal-content",onClick:h=>h.stopPropagation(),children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("span",{className:"modal-title",children:n}),e.jsx("button",{className:"modal-close-btn",onClick:a,children:"✕"})]}),e.jsxs("div",{className:"modal-body",children:[l&&e.jsx("p",{style:{color:"#8b949e",fontSize:13},children:"Loading…"}),d&&e.jsx("p",{style:{color:"#f85149",fontSize:13},children:d}),!l&&!d&&o.map((h,p)=>e.jsxs("div",{children:[e.jsxs("p",{className:"section-code-header",children:["Lines ",h.start,"–",h.end]}),e.jsx(Do,{language:m,style:Lo,customStyle:{margin:0,borderRadius:"6px",fontSize:"13px"},codeTagProps:{style:{fontFamily:"'Fira Code', 'Cascadia Code', Consolas, monospace"}},showLineNumbers:!0,startingLineNumber:h.start,children:h.code})]},p))]})]})})}function Li({project:t,triggerRef:s,onInsert:n,onClose:a}){const[o,r]=i.useState("upload"),[l,c]=i.useState(""),[d,u]=i.useState(""),[m,h]=i.useState(!1),[p,f]=i.useState(null),[k,v]=i.useState([]),[g,y]=i.useState({visibility:"hidden"}),N=i.useRef(null);i.useLayoutEffect(()=>{const $=N.current;if(!$)return;const w=$.offsetHeight,S=360;y({position:"fixed",top:Math.max(8,(window.innerHeight-w)/2),left:Math.max(8,(window.innerWidth-S)/2),width:S,visibility:"visible"})},[s]),i.useEffect(()=>{fetch(`/api/images/${encodeURIComponent(t)}`).then($=>$.json()).then($=>v($)).catch(()=>{})},[t]),i.useEffect(()=>{function $(w){N.current&&!N.current.contains(w.target)&&s.current!==w.target&&a()}return document.addEventListener("mousedown",$),()=>document.removeEventListener("mousedown",$)},[a,s]);const j=i.useCallback(async $=>{h(!0),f(null);try{const w=new FormData;w.append("file",$);const S=await fetch(`/api/images?project=${encodeURIComponent(t)}`,{method:"POST",body:w});if(!S.ok){const x=await S.json().catch(()=>({}));throw new Error(x.error??"Upload failed")}const{url:I}=await S.json();n(`![${l}](${I})`),a()}catch(w){f(w instanceof Error?w.message:"Upload failed")}finally{h(!1)}},[t,l,n,a]),b=async $=>{const w=$.target.files?.[0];w&&await j(w)};i.useEffect(()=>{const $=async w=>{const I=Array.from(w.clipboardData?.items??[]).find(B=>B.type.startsWith("image/"));if(!I)return;w.preventDefault();const x=I.getAsFile();if(!x)return;const P=x.type.split("/")[1]??"png",F=new File([x],`paste-${Date.now()}.${P}`,{type:x.type});await j(F)};return document.addEventListener("paste",$),()=>document.removeEventListener("paste",$)},[j]);const E=()=>{d.trim()&&(n(`![${l}](${d.trim()})`),a())},D=$=>{n(`![${l}](${$})`),a()};return To.createPortal(e.jsxs("div",{className:"image-insert-popover",ref:N,style:g,children:[e.jsxs("div",{className:"image-insert-header",children:[e.jsx("span",{className:"image-insert-title",children:"Insert image"}),e.jsx("button",{className:"image-insert-close",onClick:a,title:"Close",children:"✕"})]}),e.jsxs("div",{className:"image-insert-tabs",children:[e.jsx("button",{className:`image-insert-tab${o==="upload"?" active":""}`,onClick:()=>r("upload"),children:"Upload"}),e.jsx("button",{className:`image-insert-tab${o==="url"?" active":""}`,onClick:()=>r("url"),children:"URL"})]}),e.jsxs("div",{className:"image-insert-alt-row",children:[e.jsx("label",{className:"image-insert-label",children:"Alt text"}),e.jsx("input",{className:"image-insert-input",type:"text",placeholder:"Description (optional)",value:l,onChange:$=>c($.target.value)})]}),o==="upload"?e.jsxs("div",{className:"image-insert-tab-content",children:[e.jsxs("label",{className:`image-upload-label${m?" uploading":""}`,children:[e.jsx("input",{type:"file",accept:"image/*",style:{display:"none"},onChange:b,disabled:m}),m?"⏳ Uploading…":"📁 Choose a file"]}),e.jsx("p",{className:"image-paste-hint",children:"or press Ctrl+V / ⌘V to paste from clipboard"}),p&&e.jsx("div",{className:"image-insert-error",children:p})]}):e.jsxs("div",{className:"image-insert-tab-content",children:[e.jsx("input",{className:"image-insert-input",type:"text",placeholder:"https://example.com/image.png",value:d,onChange:$=>u($.target.value),onKeyDown:$=>$.key==="Enter"&&E()}),e.jsx("button",{className:"image-insert-btn-insert",onClick:E,disabled:!d.trim(),children:"Insert"})]}),k.length>0&&e.jsxs("div",{className:"image-insert-gallery-section",children:[e.jsx("div",{className:"image-insert-gallery-label",children:"Project images"}),e.jsx("div",{className:"image-thumbs",children:k.map($=>e.jsx("img",{src:$.url,alt:$.filename,className:"image-thumb",title:$.filename,onClick:()=>D($.url)},$.filename))})]})]}),document.body)}function en(t,s){return!t||t.status==="no_tracking"?"unknown":t.modified.includes(s)?"modified":t.missing.includes(s)?"missing":(t.anchors_lost??[]).includes(s)?"anchors_lost":t.unchanged.includes(s)?"ok":"unknown"}function Ti(t){if(!t)return"—";const s=new Date(t);if(Number.isNaN(s.getTime()))return"—";const n=a=>String(a).padStart(2,"0");return`${s.toLocaleDateString(void 0,{month:"short",day:"numeric"})}, ${n(s.getHours())}:${n(s.getMinutes())}`}function Mi({doc:t,isStale:s,report:n,toc:a,activeHeadingId:o,version:r,onSelectHeading:l,onSelectFile:c,onClose:d,tab:u,onTab:m,comments:h,unreadComments:p}){const f=re(),{docs:k,projects:v,currentProject:g}=X(),y=j=>!!t.tracked_files.find(E=>E.path===j)?.sections?.length&&en(n,j)!=="anchors_lost",N=h!==null&&u==="comments";return e.jsxs("aside",{className:"context-rail",children:[e.jsxs("div",{className:"rail-section rail-section--toc",children:[e.jsxs("div",{className:"rail-section-head",children:[h!==null?e.jsxs("div",{className:"rail-tabs",children:[e.jsx("button",{type:"button",className:`rail-tab${N?"":" active"}`,onClick:()=>m("page"),children:"On this page"}),e.jsxs("button",{type:"button",className:`rail-tab${N?" active":""}`,onClick:()=>m("comments"),children:["Comments",p>0&&e.jsx("span",{className:"rail-tab-count",children:p})]})]}):e.jsx("span",{className:"rail-label",children:a.length>0?"On this page":""}),e.jsx("button",{className:"rail-collapse-btn",onClick:d,title:"Hide details (Ctrl/⌘ + \\)",children:"▷|"})]}),N&&h,!N&&a.length>0&&e.jsx("nav",{className:"rail-toc",children:a.map(j=>e.jsx("button",{className:`rail-toc-item rail-toc-item--h${j.level}${o===j.id?" active":""}`,onClick:()=>l(j.id),children:j.text},j.id))})]}),!N&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"rail-section",children:[e.jsx("span",{className:"rail-label",children:"Status"}),e.jsxs("div",{className:"rail-row",children:[e.jsx("span",{className:"rail-key",children:"Freshness"}),e.jsx("span",{className:`rail-chip${s?" rail-chip--stale":" rail-chip--fresh"}`,children:s?"Outdated":"Up to date"})]}),e.jsxs("div",{className:"rail-row",children:[e.jsx("span",{className:"rail-key",children:"Last updated"}),e.jsx("span",{className:"rail-val",children:Ti(t.updatedAt)})]}),e.jsxs("div",{className:"rail-row",children:[e.jsx("span",{className:"rail-key",children:"Version"}),e.jsx("span",{className:"rail-val",children:r!==null?`v${r}`:"—"})]})]}),t.tracked_files.length>0&&e.jsxs("div",{className:"rail-section",children:[e.jsxs("span",{className:"rail-label",children:["Tracked files · ",t.tracked_files.length]}),e.jsx("div",{className:"rail-files",children:t.tracked_files.map(j=>{const b=en(n,j.path),E=y(j.path);return e.jsxs("button",{className:`rail-file${E?" rail-file--clickable":""}`,onClick:E?()=>c(j.path):void 0,title:E?`${j.path} — voir le code de la section`:j.path,children:[e.jsx("span",{className:`rail-file-dot rail-file-dot--${b}`}),e.jsx("span",{className:"rail-file-path",children:j.path})]},j.path)})}),e.jsx("div",{className:"rail-legend",children:"modified · up to date · missing · anchors lost"})]}),t.tags.length>0&&e.jsxs("div",{className:"rail-section",children:[e.jsx("span",{className:"rail-label",children:"Tags"}),e.jsx("div",{className:"rail-tags",children:t.tags.map(j=>e.jsx("span",{className:"tag-badge",children:j},j))})]}),t.related_docs&&t.related_docs.length>0&&e.jsxs("div",{className:"rail-section",children:[e.jsx("span",{className:"rail-label",children:"Related pages"}),e.jsx("div",{className:"rail-links",children:t.related_docs.map(j=>{const b=j.indexOf(":");if(b!==-1){const D=j.slice(0,b),$=j.slice(b+1);return v.includes(D)?e.jsxs("button",{className:"rail-link rail-link--cross-project",onClick:()=>f(ne(D,$)),title:`Projet : ${D}`,children:["↗ ",D," · ",$]},j):e.jsxs("span",{className:"rail-link rail-link--broken",children:[j," (projet introuvable)"]},j)}const E=k.find(D=>D.id===j);return E?e.jsxs("button",{className:"rail-link",onClick:()=>f(ne(g,j)),children:["▤ ",E.title]},j):e.jsxs("span",{className:"rail-link rail-link--broken",children:[j," (lien cassé)"]},j)})})]})]})]})}function Qt(t){return!t.root.read||t.replies.some(s=>!s.read)}function Ii(t){return[t.root.id,...t.replies.map(s=>s.id)]}function pt(t){return t===null?"an unversioned publication":`v${t}`}function Ai({data:t,locatedIds:s,activeId:n,hoveredId:a,readOnly:o,onActivate:r,onHover:l,onDelete:c}){const d=Mo(t.comments),u=d.filter(S=>!S.root.detached),m=d.filter(S=>S.root.detached),h=t.comments.filter(S=>!S.read).length,[p,f]=i.useState(h>0?"unread":"all"),[k,v]=i.useState(null),[g,y]=i.useState(!1),[N,j]=i.useState(null),b=t.publication?.id,E=t.publication?.commentsClosed===!0;if(!b)return e.jsx("div",{className:"cp-empty",children:"This document is not published: readers cannot comment on it."});const D=async S=>{y(!0),j(null);try{await S()}catch(I){j(I instanceof Error?I.message:String(I))}finally{y(!1)}},$=p==="unread"?u.filter(Qt):u,w=(S,I)=>{const{root:x}=S,P=Qt(S),F=s.has(x.id);return e.jsxs("div",{className:`cp-card${P?" cp-card--unread":""}${I?" cp-card--detached":""}${n===x.id||a===x.id?" cp-card--active":""}`,onClick:()=>r(x.id),onMouseEnter:()=>l(x.id),onMouseLeave:()=>l(null),children:[e.jsxs("div",{className:"cp-head",children:[I?e.jsx(ws,{size:12,className:"cp-state cp-state--detached"}):P?e.jsx("span",{className:"cp-dot",title:"Unread"}):e.jsx(Ee,{size:12,className:"cp-state cp-state--read"}),e.jsx("span",{className:"cp-author",title:Ls,children:Ts(x.author)}),e.jsxs("span",{className:"cp-time",title:new Date(x.createdAt).toLocaleString(),children:["· ",Ms(x.createdAt)]}),!o&&e.jsxs("span",{className:"cp-actions",onClick:B=>B.stopPropagation(),children:[P&&e.jsx("button",{type:"button",className:"cp-icon",title:"Mark as read",disabled:g,onClick:()=>D(()=>Is(b,Ii(S))),children:e.jsx(Ee,{size:14})}),e.jsx("button",{type:"button",className:"cp-icon cp-icon--danger",title:"Delete",disabled:g,onClick:()=>v(x.id),children:e.jsx(Wl,{size:14})})]})]}),x.anchor&&e.jsxs("div",{className:`cp-quote${F||I?"":" cp-quote--lost"}`,children:["« ",x.anchor.exact," »",I&&x.detached?` — ${pt(x.detached.fromVersion)}`:""]}),!I&&!F&&e.jsx("div",{className:"cp-note",children:"Passage changed since the publication: not highlighted here."}),e.jsx("div",{className:"cp-body",children:x.body}),S.replies.map(B=>e.jsxs("div",{className:`cp-reply${B.read?"":" cp-reply--unread"}`,children:[e.jsxs("div",{className:"cp-reply-head",children:[e.jsx("span",{title:Ls,children:Ts(B.author)})," · ",Ms(B.createdAt)]}),e.jsx("div",{className:"cp-body",children:B.body})]},B.id)),I&&x.detached&&e.jsxs("div",{className:"cp-note",children:["Detached when the publication went from ",pt(x.detached.fromVersion)," to"," ",pt(x.detached.toVersion)]}),k===x.id&&e.jsxs("div",{className:"cp-confirm",onClick:B=>B.stopPropagation(),children:[e.jsxs("span",{children:["Delete this comment",S.replies.length>0?` and its ${S.replies.length} replies`:"","?"]}),e.jsx("button",{type:"button",className:"cp-confirm-btn",onClick:()=>v(null),disabled:g,children:"Cancel"}),e.jsx("button",{type:"button",className:"cp-confirm-btn cp-confirm-btn--danger",disabled:g,onClick:()=>{v(null),j(null),c(b,[x.id]).catch(B=>j(B instanceof Error?B.message:String(B)))},children:"Delete"})]})]},x.id)};return e.jsxs("div",{className:"cp",children:[e.jsxs("div",{className:"cp-toolbar",children:[e.jsxs("button",{type:"button",className:`cp-filter${p==="unread"?" active":""}`,onClick:()=>f("unread"),children:["Unread · ",d.filter(Qt).length]}),e.jsxs("button",{type:"button",className:`cp-filter${p==="all"?" active":""}`,onClick:()=>f("all"),children:["All · ",u.length]}),!o&&h>0&&e.jsx("button",{type:"button",className:"cp-mark-all",disabled:g,onClick:()=>D(()=>Is(b,null)),children:"Mark all as read"})]}),e.jsxs("div",{className:"cp-usage",children:[e.jsxs("span",{children:[t.comments.length," / ",t.limit," comments on the published ",pt(t.publication?.version??null),E&&" · closed to new comments"]}),!o&&e.jsx("button",{type:"button",className:"cp-close-toggle",disabled:g,title:E?"Let readers add comments again":"Readers keep seeing the comments but can no longer add any",onClick:()=>D(()=>Io(b,!E)),children:E?"Reopen comments":"Close comments"})]}),N&&e.jsx("div",{className:"cp-error",children:N}),$.length===0?m.length===0&&e.jsx("div",{className:"cp-empty",children:p==="unread"?"No unread comment.":"No comment yet."}):$.map(S=>w(S,!1)),m.length>0&&e.jsxs("div",{className:"cp-detached",children:[e.jsxs("span",{className:"rail-label",children:["Detached · ",m.length]}),e.jsx("div",{className:"cp-detached-text",children:"Their passage is absent from the published version: readers no longer see them. They still count toward the limit until deleted."}),m.map(S=>w(S,!0))]})]})}function _i(t,s){const{commentsVersion:n,publicationsVersion:a}=X(),[o,r]=i.useState(null),[l,c]=i.useState(0),[d,u]=i.useState(new Set),m=`${t}\0${s??""}`;i.useEffect(()=>{if(!s)return;let v=!1;return Ao(t,s).then(g=>{v||r({key:m,data:g})}).catch(g=>console.error(`Comments of "${s}" could not be loaded: ${g.message}`)),()=>{v=!0}},[m,t,s,n,a,l]);const h=i.useCallback(()=>c(v=>v+1),[]),p=i.useCallback(async(v,g)=>{u(y=>new Set([...y,...g]));try{await _o(v,g)}catch(y){throw u(N=>new Set([...N].filter(j=>!g.includes(j)))),y}},[]),f=o?.key===m?o.data:null;return{data:i.useMemo(()=>{if(!f||d.size===0)return f;const v=f.comments.filter(g=>!d.has(g.id)&&!(g.parentId&&d.has(g.parentId)));return v.length===f.comments.length?f:{...f,comments:v}},[f,d]),reload:h,remove:p}}function zi(){const{currentProject:t,commentsVersion:s,publicationsVersion:n,hasReceivedInitialState:a,setCommentSummary:o}=X();i.useEffect(()=>{if(!a)return;let r=!1;return zo(t).then(l=>{r||o(t,l)}).catch(l=>console.error(`Comment counts of "${t}" could not be loaded: ${l.message}`)),()=>{r=!0}},[t,s,n,a])}function Fi(t){const{commentSummary:s,currentProject:n}=X();return!t||s.project!==n?null:s.docs[t]??null}function Ka(){const[t,s]=i.useState(!1);return{copied:t,copy:async a=>{await navigator.clipboard.writeText(a),s(!0),setTimeout(()=>s(!1),2e3)}}}function Ja(t){const{publicationsVersion:s}=X(),[n,a]=i.useState(null),[o,r]=i.useState(null),[l,c]=i.useState(0);i.useEffect(()=>{let u=!1;return Fo(t).then(m=>{u||(a({project:t,publications:m}),r(null))}).catch(m=>{u||r(m.message)}),()=>{u=!0}},[t,s,l]);const d=i.useCallback(()=>c(u=>u+1),[]);return{publications:n?.project===t?n.publications:null,error:o,reload:d}}function Oi({project:t,doc:s,latestVersion:n,readOnly:a}){const{publications:o,reload:r}=Ja(t),[l,c]=i.useState(!1),d=o?.find(m=>m.docId===s.id)??null;if(i.useEffect(()=>{if(!l)return;const m=h=>{h.key==="Escape"&&c(!1)};return window.addEventListener("keydown",m),()=>window.removeEventListener("keydown",m)},[l]),o===null||!d&&a)return null;const u=()=>{l||r(),c(!l)};return e.jsxs("div",{className:"menu-anchor",children:[e.jsxs("button",{className:`btn-secondary publish-btn${l?" publish-btn--open":""}`,onClick:u,title:d?"Public link of this document":"Publish this document",children:[e.jsx(Mt,{size:14,className:d?"publish-btn-icon--published":void 0}),d?"Published":"Publish",d?.status==="modified"&&e.jsx("span",{className:"publish-btn-dot",title:"Changed since it was published"})]}),l&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"menu-backdrop",onClick:()=>c(!1)}),e.jsx("div",{className:"publish-popover",role:"dialog","aria-label":d?"Document published":"Publish this document",children:d?e.jsx(Hi,{publication:d,readOnly:a,onClose:()=>c(!1),onChanged:r}):e.jsx(Ui,{project:t,doc:s,latestVersion:n,onClose:()=>c(!1),onChanged:r})})]})]})}function Ya({title:t,published:s,onClose:n}){return e.jsxs("div",{className:"publish-head",children:[s&&e.jsx("span",{className:"publish-online-dot"}),e.jsx("span",{className:"publish-title",children:t}),e.jsx("button",{className:"publish-close",onClick:n,"aria-label":"Close",children:e.jsx(pn,{size:14})})]})}function Xa({label:t,value:s,onChange:n,placeholder:a,multiline:o}){return e.jsxs("label",{className:"publish-field",children:[e.jsxs("span",{className:"publish-field-label",children:[t," ",e.jsx("span",{className:"publish-field-optional",children:"(optional)"})]}),o?e.jsx("textarea",{className:"publish-input publish-input--multiline",value:s,maxLength:ts,rows:3,placeholder:a,onChange:r=>n(r.target.value),autoFocus:!0}):e.jsx("input",{className:"publish-input",value:s,maxLength:ts,placeholder:a,onChange:r=>n(r.target.value)})]})}function Ui({project:t,doc:s,latestVersion:n,onClose:a,onChanged:o}){const[r,l]=i.useState(""),[c,d]=i.useState(!1),[u,m]=i.useState(null),h=async()=>{d(!0),m(null);try{await Oo(t,s.id,r),o()}catch(p){m(p instanceof Error?p.message:String(p))}finally{d(!1)}};return e.jsxs(e.Fragment,{children:[e.jsx(Ya,{title:"Publish this document",onClose:a}),e.jsx("p",{className:"publish-text",children:"The public link shows the current version, frozen. Later changes only appear there once the publication is updated."}),e.jsxs("div",{className:"publish-version",children:[e.jsx(Al,{size:14}),"Version ",Te(n)," · modified ",us(s.updatedAt)]}),e.jsx(Xa,{label:"Version note",value:r,onChange:l,placeholder:"e.g. First version shared with the infra team",multiline:!0}),e.jsxs("div",{className:"publish-access",children:[e.jsx(mn,{size:14}),"Anyone with the link can read this document."]}),u&&e.jsx("div",{className:"publish-error",children:u}),e.jsxs("div",{className:"publish-actions",children:[e.jsx("button",{className:"btn-secondary",onClick:a,disabled:c,children:"Cancel"}),e.jsxs("button",{className:"btn-primary",onClick:h,disabled:c,children:[e.jsx(Mt,{size:14}),c?"Publishing…":"Publish"]})]})]})}function Hi({publication:t,readOnly:s,onClose:n,onChanged:a}){const[o,r]=i.useState(""),[l,c]=i.useState(!1),[d,u]=i.useState(null),[m,h]=i.useState(!1),{copied:p,copy:f}=Ka(),k=hn(t.token),v=t.status==="modified",g=async y=>{c(!0),u(null);try{await y(),r(""),h(!1),a()}catch(N){u(N instanceof Error?N.message:String(N))}finally{c(!1)}};return e.jsxs(e.Fragment,{children:[e.jsx(Ya,{title:"Document published",published:!0,onClose:n}),e.jsxs("div",{className:"publish-link",children:[e.jsx(mn,{size:14,className:"publish-link-icon"}),e.jsx("span",{className:"publish-link-url",title:k,children:k}),e.jsx("a",{className:"publish-icon-btn",href:k,target:"_blank",rel:"noopener noreferrer",title:"Open the public page",children:e.jsx(na,{size:14})}),e.jsx("button",{className:"publish-copy-btn",onClick:()=>f(k),title:"Copy the link",children:p?e.jsx(Ee,{size:14}):e.jsx(Lt,{size:14})})]}),e.jsxs("div",{className:"publish-meta",children:["Published ",us(t.publishedAt)," · version ",Te(t.version)]}),t.note&&e.jsx("div",{className:"publish-quote",children:t.note}),e.jsx("div",{className:"publish-sep"}),v?e.jsxs("div",{className:"publish-warning",children:[e.jsx(Ns,{size:14}),e.jsxs("div",{children:["The document changed since it was published.",e.jsx("br",{}),"Published: ",Te(t.version)," · current: ",Te(t.currentVersion)]})]}):e.jsxs("div",{className:"publish-uptodate",children:[e.jsx(Xe,{size:14}),"The published version is up to date."]}),!s&&v&&!m&&e.jsx(Xa,{label:"Note for the new version",value:o,onChange:r,placeholder:"e.g. Added the Entry points section"}),d&&e.jsx("div",{className:"publish-error",children:d}),!s&&(m?e.jsx(Qa,{busy:l,onCancel:()=>h(!1),onConfirm:()=>g(()=>fn(t.id))}):e.jsxs("div",{className:"publish-actions publish-actions--split",children:[e.jsxs("button",{className:"btn-secondary publish-danger-btn",onClick:()=>h(!0),disabled:l,children:[e.jsx(ws,{size:14}),"Unpublish"]}),v&&e.jsxs("button",{className:"btn-primary",onClick:()=>g(()=>gn(t.id,o)),disabled:l,children:[e.jsx(Ct,{size:14}),l?"Updating…":"Update publication"]})]}))]})}function Qa({title:t,busy:s,onCancel:n,onConfirm:a}){return e.jsxs("div",{className:"publish-confirm",children:[e.jsx("div",{className:"publish-confirm-title",children:t?`Unpublish “${t}”?`:"Unpublish this document?"}),e.jsx("div",{className:"publish-confirm-text",children:"The link stops working immediately. Publishing again creates a new link."}),e.jsxs("div",{className:"publish-actions",children:[e.jsx("button",{className:"btn-secondary",onClick:n,disabled:s,children:"Cancel"}),e.jsx("button",{className:"publish-confirm-btn",onClick:a,disabled:s,children:s?"Unpublishing…":"Unpublish"})]})]})}function tn(t){return t.replace(/[^a-zA-Z0-9_\-. ]/g,"_")}const Bi=1280,ls="mcp-documentor.contextRail",Ze=()=>typeof window>"u"||window.innerWidth>=Bi;function Wi(){try{const t=JSON.parse(localStorage.getItem(ls)??"null");return t&&t.wide===Ze()?t.open:null}catch{return null}}function Zt(t){try{t===null?localStorage.removeItem(ls):localStorage.setItem(ls,JSON.stringify({open:t,wide:Ze()}))}catch{}}function sn(t){if(!t)return"the last snapshot";const s=new Date(t);if(Number.isNaN(s.getTime()))return"the last snapshot";const n=a=>String(a).padStart(2,"0");return`${s.toLocaleDateString(void 0,{month:"short",day:"numeric",year:"numeric"})} ${n(s.getHours())}:${n(s.getMinutes())}`}function Vi(){const t=re(),s=X(),{selectedDoc:n,selectedDocId:a,freshnessResult:o,setFreshnessResult:r,setSelectedDoc:l,setDocs:c,docs:d,currentProject:u,projects:m,historyEntries:h,historyVersionContent:p,setHistoryEntries:f,setHistoryVersionContent:k,readOnly:v,codeSourcesVersion:g}=s,y=i.useRef(null),N=i.useRef(null),j=i.useRef(null),[b,E]=i.useState("document"),[D,$]=i.useState(null),[w,S]=i.useState(!1),[I,x]=i.useState(!1),[P,F]=i.useState(!1),[B,W]=i.useState(!1),[G,L]=i.useState(!1),[q,T]=i.useState(""),[V,Y]=i.useState(!1),[be,ue]=i.useState(null),[Ue,ye]=i.useState(!1),[$e,Ne]=i.useState(null),[ot,Re]=i.useState(null),[He,te]=i.useState(!1),[pe,he]=i.useState(!1),[Pe,De]=i.useState(!1),[Me,we]=i.useState(null),[M,U]=i.useState(!1),[K,J]=i.useState(!1),[fe,At]=i.useState([]),[ho,_t]=i.useState(null),[Ss,Be]=i.useState(()=>Wi()??Ze()),[mo,We]=i.useState("page"),[ge,po]=i.useState(null),[zt,Ft]=i.useState(null),[Ot,rt]=i.useState(null),Es=i.useRef(null),Ut=C=>{Zt(C),Be(C)},$s=b==="diff",Rs=b==="history";i.useEffect(()=>{window.__pdfReady=!!(n&&!G)},[n,G]),i.useEffect(()=>{let C=Ze();const R=()=>{const _=Ze();_!==C&&(C=_,Zt(null),Be(_))};return window.addEventListener("resize",R),()=>window.removeEventListener("resize",R)},[]),i.useEffect(()=>{const C=R=>{(R.metaKey||R.ctrlKey)&&R.key==="\\"&&(R.preventDefault(),Be(_=>(Zt(!_),!_)))};return window.addEventListener("keydown",C),()=>window.removeEventListener("keydown",C)},[]),i.useEffect(()=>{if(!a)return;window.__pdfReady=!1,window.__mermaidPending=0,y.current&&(y.current.scrollTop=0),E("document"),$(null),F(!1),f(null),L(!1),ue(null),Ne(null),he(!1),we(null),U(!1),J(!1),At([]),_t(null),We("page"),Ft(null),rt(null);const C=xe(a),R=new AbortController;let _=!1;const H=encodeURIComponent(u);return fetch(`/api/doc/${C}?project=${H}`,{signal:R.signal}).then(z=>z.json()).then(z=>{_||(z.doc?l(z.doc):F(!0))}).catch(z=>{_||z.name==="AbortError"||F(!0)}),fetch(`/api/freshness/${C}?project=${H}`,{signal:R.signal}).then(z=>z.json()).then(z=>{_||!z.report||r(z.report)}).catch(()=>{}),fetch(`/api/history/${C}?project=${H}`,{signal:R.signal}).then(z=>z.json()).then(z=>{_||f(z.versions??[])}).catch(()=>{}),()=>{_=!0,R.abort()}},[a,u]),i.useEffect(()=>{if(g===0||!a)return;const C=new AbortController;return fetch(`/api/freshness/${xe(a)}?project=${encodeURIComponent(u)}`,{signal:C.signal}).then(R=>R.json()).then(R=>{R.report&&r(R.report)}).catch(()=>{}),()=>C.abort()},[g]),i.useEffect(()=>{if(b!=="document"||G||!n){At([]);return}const C=requestAnimationFrame(()=>{const R=y.current?.querySelector(".doc-content");if(!R)return;const _=[...R.querySelectorAll("h1, h2, h3")];At(_.filter(H=>H.id).map(H=>({id:H.id,text:H.textContent??"",level:Number(H.tagName.slice(1))})))});return()=>cancelAnimationFrame(C)},[n,b,G]),i.useEffect(()=>{const C=y.current;if(!C||fe.length===0)return;const R=()=>{const _=C.getBoundingClientRect().top+80;let H=fe[0].id;for(const z of fe){const se=document.getElementById(z.id);se&&se.getBoundingClientRect().top<=_&&(H=z.id)}_t(H)};return R(),C.addEventListener("scroll",R,{passive:!0}),()=>C.removeEventListener("scroll",R)},[fe]);const fo=i.useCallback(C=>{document.getElementById(C)?.scrollIntoView({behavior:"smooth",block:"start"}),_t(C)},[]),Ce=_i(u,n?.id),ke=Fi(n?.id),lt=Uo(ge),go=i.useMemo(()=>(Ce.data?.comments??[]).filter(C=>!C.parentId&&!C.detached),[Ce.data]),me=Ho(lt,go),xo=(Ce.data?.comments??[]).filter(C=>!C.read).length;i.useEffect(()=>{const C=Ce.data;!n||!C||Es.current===n.id||(Es.current=n.id,C.comments.some(R=>!R.read)&&(We("comments"),Be(!0)))},[Ce.data,n]),i.useEffect(()=>{ut("dc-passage",[...me.values()].map(_=>_.range));const C=Ot??zt,R=C?me.get(C):void 0;ut("dc-focus",R?[R.range]:[])},[me,Ot,zt]),i.useEffect(()=>()=>{ut("dc-passage",[]),ut("dc-focus",[])},[]);const Ht=i.useCallback((C,R)=>{if(!lt)return null;const _=Bo(C,R),H=_?lt.indexAt(_.node,_.offset):null;if(H===null)return null;for(const[z,se]of me)if(H>=se.start&&H<se.end)return z;return null},[lt,me]);i.useEffect(()=>{if(!ge||me.size===0)return;const C=z=>{if(!window.getSelection()?.isCollapsed||z.target.closest("a, button"))return;const se=Ht(z.clientX,z.clientY);se&&(Ft(se),We("comments"),Be(!0))};let R=0;const _=z=>{cancelAnimationFrame(R),R=requestAnimationFrame(()=>rt(Ht(z.clientX,z.clientY)))},H=()=>{cancelAnimationFrame(R),rt(null)};return ge.addEventListener("click",C),ge.addEventListener("mousemove",_),ge.addEventListener("mouseleave",H),()=>{cancelAnimationFrame(R),ge.removeEventListener("click",C),ge.removeEventListener("mousemove",_),ge.removeEventListener("mouseleave",H)}},[ge,me,Ht]);const vo=i.useCallback(C=>{Ft(C),me.get(C)?.range.startContainer.parentElement?.scrollIntoView({behavior:"smooth",block:"center"})},[me]),Bt=i.useMemo(()=>({code:Wo,a({href:C,children:R,..._}){if(C?.startsWith("doc://")){const H=ql(C.slice(6)),z=H.indexOf(":");if(z!==-1){const ae=H.slice(0,z),Ge=H.slice(z+1),Ke=m.includes(ae);return e.jsx("button",{className:Ke?"doc-inline-link doc-inline-link--cross-project":"doc-inline-link doc-inline-link--broken",onClick:()=>{Ke&&t(ne(ae,Ge))},title:Ke?`Projet : ${ae}`:`Projet introuvable : ${ae}`,children:R})}const se=H,qe=d.some(ae=>ae.id===se);return e.jsx("button",{className:qe?"doc-inline-link":"doc-inline-link doc-inline-link--broken",onClick:()=>{qe&&t(ne(u,se))},title:qe?void 0:`Document introuvable : ${se}`,children:R})}return C?.startsWith("#")?e.jsx("a",{href:C,onClick:H=>{H.preventDefault(),document.getElementById(C.slice(1))?.scrollIntoView({behavior:"smooth"})},..._,children:R}):e.jsx("a",{href:C,target:"_blank",rel:"noopener noreferrer",..._,children:R})},img({src:C,alt:R,..._}){return e.jsx("img",{src:C,alt:R??"",className:"doc-image",..._})}}),[d,m,u,t]),jo=i.useMemo(()=>n&&e.jsx(cn,{remarkPlugins:[un],rehypePlugins:[dn],components:Bt,urlTransform:C=>C.startsWith("doc://")?C:Vo(C),children:n.content}),[n,Bt]);if(!n&&!a)return e.jsx("div",{className:"doc-viewer",children:e.jsx("div",{className:"doc-viewer-empty",children:"Select a documentation entry to view"})});if(a&&P&&!n)return e.jsx("div",{className:"doc-viewer",children:e.jsx("div",{className:"doc-viewer-empty",children:"No documentation at this path in the current project."})});const bo=async()=>{if(n)try{const R=await(await fetch(`/api/freshness/${xe(n.id)}?project=${encodeURIComponent(u)}`)).json();R.report&&r(R.report)}catch{}},yo=async()=>{n&&(await navigator.clipboard.writeText(n.content),x(!0),setTimeout(()=>x(!1),2e3))},No=()=>{if(!n)return;const C=new Blob([n.content],{type:"text/markdown;charset=utf-8"}),R=URL.createObjectURL(C),_=document.createElement("a");_.href=R,_.download=`${tn(n.title)}.md`,document.body.appendChild(_),_.click(),document.body.removeChild(_),URL.revokeObjectURL(R)},wo=async()=>{if(!n)return;const C=Number(localStorage.getItem("printScale")??100)/100,R=u,_=n.id;ye(!0),Ne(null);try{const H=new URLSearchParams({project:R,docId:_,scale:String(C)}),z=await fetch(`/api/pdf?${H}`);if(z.status===503){const Ge=await z.json();Ne(Ge.message??"Navigateur introuvable pour la génération PDF."),setTimeout(()=>Ne(null),8e3);return}if(!z.ok){Ne("Échec de la génération PDF."),setTimeout(()=>Ne(null),5e3);return}const se=await z.blob(),qe=await new Promise((Ge,Ke)=>{const dt=new FileReader;dt.onload=()=>Ge(dt.result),dt.onerror=Ke,dt.readAsDataURL(se)}),ae=document.createElement("a");ae.href=qe,ae.download=`${tn(n.title)}.pdf`,document.body.appendChild(ae),ae.click(),document.body.removeChild(ae)}finally{ye(!1)}},Co=async()=>{if(!(!n||h!==null)){W(!0);try{const R=await(await fetch(`/api/history/${xe(n.id)}?project=${encodeURIComponent(u)}`)).json();f(R.versions??[])}catch{f([])}finally{W(!1)}}},ko=async()=>{if(!(!n||D!==null)){S(!0);try{const R=await(await fetch(`/api/git-diff/${xe(n.id)}?project=${encodeURIComponent(u)}`)).json();$(R.diff??R.error??"No diff available.")}catch{$("Failed to load diff.")}finally{S(!1)}}},Ve=C=>{E(C),U(!1),J(!1),C!=="document"&&L(!1),C==="diff"&&ko(),C==="history"&&Co()},So=C=>{const R=N.current;if(!R)return;const _=R.selectionStart,H=R.selectionEnd,z=q.slice(0,_)+C+q.slice(H);T(z),requestAnimationFrame(()=>{R.selectionStart=R.selectionEnd=_+C.length,R.focus()})},Eo=async()=>{if(n){Y(!0),ue(null);try{const C=xe(n.id),R=await fetch(`/api/doc/${C}?project=${encodeURIComponent(u)}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:q})}),_=await R.json();if(!R.ok||_.error)throw new Error(_.error||"Save failed");const H=new Date().toISOString();l({...n,content:q,updatedAt:H}),c(d.map(z=>z.id===n.id?{...z,updatedAt:H}:z)),L(!1)}catch(C){ue(C instanceof Error?C.message:"Save failed")}finally{Y(!1)}}},$o=async()=>{if(n){De(!0),we(null);try{const C=xe(n.id),R=await fetch(`/api/doc/${C}?project=${encodeURIComponent(u)}`,{method:"DELETE"}),_=await R.json();if(!R.ok||_.error)throw new Error(_.error||"Delete failed");const H=n.id;c(d.filter(z=>z.id!==H)),l(null),r(null),he(!1),t(ne(u,null),{replace:!0})}catch(C){we(C instanceof Error?C.message:"Delete failed")}finally{De(!1)}}},Wt=n?d.find(C=>C.id===n.id):void 0,Ps=Wt?.isStale??!1,Le=n?.tracked_files.length??0,it=o?.modified.length??0,ct=h&&h.length>0?h[0].version:null,Ds=n&&Le>0?n.tracked_files.map(C=>C.lastModifiedAt).filter(Boolean).sort().slice(-1)[0]:void 0,Ro=[...Wt?.folder?Wt.folder.split("/").filter(Boolean):[],n?.title??"…"],Po=!v&&!!n&&b==="document";return e.jsxs("div",{className:"doc-viewer",children:[e.jsxs("div",{className:"doc-main",ref:y,children:[e.jsxs("div",{className:"doc-topbar",children:[e.jsxs("div",{className:"doc-topbar-left",children:[e.jsxs("div",{className:"doc-breadcrumb",children:[e.jsx("button",{className:"nav-btn",onClick:()=>t(-1),title:"Go back",children:"←"}),e.jsx("button",{className:"nav-btn",onClick:()=>t(1),title:"Go forward",children:"→"}),Ro.map((C,R)=>e.jsxs("span",{className:"doc-breadcrumb-segment",children:[R>0&&e.jsx("span",{className:"doc-breadcrumb-sep",children:"/"}),C]},`${C}-${R}`))]}),e.jsx("h1",{className:"doc-title",children:n?.title??"…"})]}),e.jsxs("div",{className:"doc-actions",children:[!Ss&&n&&e.jsx("button",{className:"icon-btn",onClick:()=>Ut(!0),title:"Show details (Ctrl/⌘ + \\)",children:"|◁"}),n&&!G&&ke&&ke.total>0&&e.jsxs("button",{className:"btn-secondary doc-comments-btn",onClick:()=>{We("comments"),Ut(!0)},title:ke.unread>0?`${ke.total} comments, ${ke.unread} unread`:`${ke.total} comments`,children:[e.jsx(ds,{size:13}),ke.total,ke.unread>0&&e.jsx("span",{className:"doc-comments-dot"})]}),n&&!G&&e.jsx(Oi,{project:u,doc:n,latestVersion:ct,readOnly:v},n.id),Po&&e.jsx("button",{className:`btn-primary${G?" active":""}`,onClick:()=>{!G&&n&&T(n.content),L(!G),ue(null)},title:G?"Cancel editing":"Edit document",children:G?"✕ Cancel":"✎ Edit"}),n&&!G&&e.jsxs("div",{className:"menu-anchor",children:[e.jsx("button",{className:"btn-secondary",onClick:()=>{U(C=>!C),J(!1)},title:"Export this document",children:"↓ Export ▾"}),M&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"menu-backdrop",onClick:()=>U(!1)}),e.jsxs("div",{className:"menu-popover",children:[e.jsx("button",{className:"menu-item",onClick:()=>{U(!1),yo()},children:I?"✓ Copied!":"⎘ Copy markdown"}),e.jsx("button",{className:"menu-item",onClick:()=>{U(!1),No()},children:"↓ Download .md"}),e.jsx("button",{className:"menu-item",disabled:Ue,onClick:()=>{U(!1),wo()},children:Ue?"⏳ PDF…":"↓ Download PDF"})]})]})]}),n&&!G&&e.jsxs("div",{className:"menu-anchor",children:[e.jsx("button",{className:"btn-icon-secondary",onClick:()=>{J(C=>!C),U(!1)},title:"More actions",children:"⋯"}),K&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"menu-backdrop",onClick:()=>J(!1)}),e.jsxs("div",{className:"menu-popover menu-popover--right",children:[Le>0&&e.jsx("button",{className:"menu-item",onClick:()=>{J(!1),bo()},children:"⟳ Re-check freshness"}),e.jsx("button",{className:"menu-item",onClick:()=>{J(!1),navigator.clipboard.writeText(n.id)},children:"⎘ Copy doc ID"}),!v&&e.jsx("button",{className:"menu-item menu-item--danger",onClick:()=>{J(!1),we(null),he(!0)},children:"🗑 Delete document"})]})]})]})]})]}),e.jsxs("nav",{className:"doc-tabs",children:[e.jsx("button",{className:`doc-tab${b==="document"?" active":""}`,onClick:()=>Ve("document"),children:"Document"}),Le>0&&e.jsx("button",{className:`doc-tab${$s?" active":""}`,onClick:()=>Ve("diff"),children:w?"Diff…":`Diff${it>0?` · ${it}`:""}`}),e.jsx("button",{className:`doc-tab${Rs?" active":""}`,onClick:()=>Ve("history"),children:B?"History…":`History${ct!==null?` · v${ct}`:""}`}),Le>0&&e.jsxs("button",{className:`doc-tab${b==="files"?" active":""}`,onClick:()=>Ve("files"),children:["Tracked files · ",Le]})]}),$e&&e.jsx("div",{className:"pdf-error-banner",children:$e}),b==="document"&&!G&&Ps&&Le>0&&e.jsxs("div",{className:"stale-banner",children:[e.jsx("span",{className:"stale-banner-icon",children:"⚠"}),e.jsxs("div",{className:"stale-banner-body",children:[e.jsx("span",{className:"stale-banner-text",children:it>0?`${it} of ${Le} tracked files changed since the snapshot taken on ${sn(Ds)}.`:`Tracked files changed since the snapshot taken on ${sn(Ds)}.`}),e.jsx("button",{className:"stale-banner-link",onClick:()=>Ve("diff"),children:"View diff"})]})]}),b==="files"&&n&&(o?e.jsx(pi,{report:o,trackedFiles:n.tracked_files,docId:n.id,onViewCode:Re}):e.jsx("div",{className:"doc-tab-loading",children:"Checking tracked files…"})),Rs&&n&&e.jsx($i,{docId:n.id,project:u,entries:h??[],selectedVersion:p,onSelectVersion:async C=>{const _=await(await fetch(`/api/history-version/${xe(n.id)}/${C}?project=${encodeURIComponent(u)}`)).json();k(_??null)},markdownComponents:Bt}),$s&&(w&&D===null?e.jsx("div",{className:"doc-tab-loading",children:"Loading diff…"}):e.jsx(xi,{diffText:D??""})),b==="document"&&(G&&n?e.jsxs("div",{className:"doc-editor",children:[e.jsx("textarea",{ref:N,className:"doc-editor-textarea",value:q,onChange:C=>T(C.target.value),spellCheck:!1}),e.jsxs("div",{className:"doc-editor-actions",children:[be&&e.jsx("span",{className:"doc-editor-error",children:be}),e.jsxs("div",{className:"doc-editor-actions-right",children:[e.jsx("button",{ref:j,type:"button",className:"image-insert-trigger-btn",onClick:()=>te(C=>!C),title:"Insert image",children:"🖼 Image"}),He&&e.jsx(Li,{project:u,triggerRef:j,onInsert:So,onClose:()=>te(!1)}),e.jsx("button",{type:"button",className:"save-btn",onClick:Eo,disabled:V,children:V?"Saving…":"✓ Save"})]})]})]}):e.jsx("div",{className:"doc-content",ref:po,children:jo}))]}),Ss&&n&&e.jsx(Mi,{doc:n,isStale:Ps,report:o,toc:fe,activeHeadingId:ho,version:ct,onSelectHeading:fo,onSelectFile:Re,onClose:()=>Ut(!1),tab:mo,onTab:We,unreadComments:xo,comments:Ce.data?.publication?e.jsx(Ai,{data:Ce.data,locatedIds:new Set(me.keys()),activeId:zt,hoveredId:Ot,readOnly:v,onActivate:C=>{b!=="document"&&E("document"),vo(C)},onHover:rt,onDelete:Ce.remove},n.id):null}),pe&&n&&e.jsx("div",{className:"modal-overlay",onClick:()=>!Pe&&he(!1),children:e.jsxs("div",{className:"modal-content delete-modal",onClick:C=>C.stopPropagation(),children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("span",{className:"modal-title",children:"Delete documentation"}),e.jsx("button",{className:"modal-close-btn",onClick:()=>he(!1),disabled:Pe,children:"✕"})]}),e.jsxs("div",{className:"modal-body",children:[e.jsxs("p",{className:"delete-modal-text",children:["Delete ",e.jsx("strong",{children:n.title})," (",e.jsx("code",{children:n.id}),") from project"," ",e.jsx("strong",{children:u}),"? This action cannot be undone from the interface."]}),Me&&e.jsx("span",{className:"doc-editor-error",children:Me}),e.jsxs("div",{className:"delete-modal-actions",children:[e.jsx("button",{type:"button",className:"copy-btn",onClick:()=>he(!1),disabled:Pe,children:"Cancel"}),e.jsx("button",{type:"button",className:"delete-btn delete-btn--confirm",onClick:$o,disabled:Pe,children:Pe?"Deleting…":"🗑 Delete"})]})]})]})}),ot&&n&&e.jsx(Di,{docId:n.id,project:u,filePath:ot,onClose:()=>Re(null)})]})}async function ks(t,s){const n=await fetch(t,s);let a=null;try{a=await n.json()}catch{}if(!n.ok)throw new Error(a?.error??`HTTP ${n.status}`);return a}function qi(){return ks("/api/logs")}function Gi(t,s){const n=s?`?knownSize=${s.size}&knownMtime=${encodeURIComponent(s.mtime??"")}`:"";return ks(`/api/logs/${t}${n}`)}function Ki(){return ks("/api/logs/open-folder",{method:"POST"})}const Ji=t=>`/api/logs/${t}/download`;function et(t){return t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(t<10*1024?1:0)} KB`:`${(t/(1024*1024)).toFixed(1)} MB`}function ee(t){return t.toLocaleString("fr-FR")}function Za(t,s){return t.getFullYear()===s.getFullYear()&&t.getMonth()===s.getMonth()&&t.getDate()===s.getDate()}function It(t){return Za(new Date(t),new Date)}function eo(t){const s=new Date(t);if(Number.isNaN(s.getTime()))return t;const n=(o,r=2)=>String(o).padStart(r,"0"),a=`${n(s.getHours())}:${n(s.getMinutes())}:${n(s.getSeconds())}.${n(s.getMilliseconds(),3)}`;return Za(s,new Date)?a:`${n(s.getDate())}/${n(s.getMonth()+1)} ${a.slice(0,8)}`}function ft(t){return`${ee(t)} ms`}const to={hour:"Last hour",today:"Today",day:"Last 24 hours",week:"Last 7 days",all:"All loaded"};function so(t,s){if(s==="all")return!0;if(s==="today")return It(t);const n=Date.now()-new Date(t).getTime(),a=s==="hour"?36e5:s==="day"?864e5:7*864e5;return n<=a}const Yi=3e3;function no(t,s,n){i.useEffect(()=>{if(!s||(t(),!n))return;const a=setInterval(t,Yi);return()=>clearInterval(a)},[s,n,t])}function is(t,s,n){const[a,o]=i.useState(null),[r,l]=i.useState(null),[c,d]=i.useState(null),u=i.useRef(void 0),m=i.useRef(!1),h=i.useCallback(async()=>{if(!m.current){m.current=!0;try{const p=await Gi(t,u.current);"unchanged"in p||(u.current=p.file,o(p)),l(null),d(Date.now())}catch(p){l(p instanceof Error?p.message:String(p))}finally{m.current=!1}}},[t]);return no(h,s,n),{data:a,error:r,checkedAt:c}}function Xi(t){const[s,n]=i.useState(null),[a,o]=i.useState(null),r=i.useCallback(async()=>{try{n(await qi()),o(null)}catch(l){o(l instanceof Error?l.message:String(l))}},[]);return no(r,!0,t),{directory:s,error:a}}function Qi(t=1e3){const[s,n]=i.useState(()=>Date.now());return i.useEffect(()=>{const a=setInterval(()=>n(Date.now()),t);return()=>clearInterval(a)},[t]),s}function Zi(){const{syncEnabled:t,readOnly:s,currentProject:n}=X(),[a,o]=i.useState(null),[r,l]=i.useState(!1),[c,d]=i.useState(null),u=i.useCallback(async()=>{try{const v=await fetch("/api/sync/status"),g=await v.json();o(v.ok&&!g.error?g:null)}catch{o(null)}},[]);if(i.useEffect(()=>{!t||s||u()},[t,s,n,u]),!t||s)return null;const m=async()=>{if(!r){l(!0),d(null);try{const v=await fetch("/api/sync",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({})}),g=await v.json();!v.ok||g.error?d({ok:!1,message:g.error??`HTTP ${v.status}`}):d({ok:!0,message:g.message??"Sync terminée."})}catch(v){d({ok:!1,message:v?.message??"Sync failed"})}finally{l(!1),u()}}},h=[];a?.ahead&&h.push(`↑${a.ahead}`),a?.behind&&h.push(`↓${a.behind}`),a?.dirty?.length&&h.push(`●${a.dirty.length}`);const p=a?.conflicted?.length??0,f=r?"Sync…":p>0?`Conflits à résoudre (${p} fichier(s))`:["Sync",a?.branch,...h.length>0?[h.join(" ")]:[]].filter(Boolean).join(" · "),k=p>0?"!":h[0];return e.jsxs("div",{className:"sync-button-wrapper",children:[e.jsxs("button",{className:`rail-btn${p>0?" conflict":""}`,onClick:m,disabled:r,"data-tooltip":f,"aria-label":f,children:[e.jsx(Ct,{size:20,className:r?"spinning":void 0}),k&&e.jsx("span",{className:`rail-badge rail-badge--${p>0?"danger":"accent"}`,children:k})]}),c&&e.jsxs("div",{className:`sync-result${c.ok?"":" error"}`,children:[e.jsx("pre",{children:c.message}),e.jsx("button",{className:"sync-result-close",onClick:()=>d(null),title:"Fermer",children:"✕"})]})]})}function Se({icon:t,label:s,active:n,onClick:a,children:o}){return e.jsxs("button",{className:`rail-btn${n?" active":""}`,onClick:a,"data-tooltip":s,"aria-label":s,children:[e.jsx(t,{size:20}),o]})}function ec({active:t,onSelect:s,onOpenSettings:n,onOpenProjectSettings:a}){const{docs:o,commentSummary:r,currentProject:l}=X(),c=o.filter(h=>h.isStale).length,d=r.project===l?Object.values(r.docs).reduce((h,p)=>h+p.unread,0):0,u=is("github",!0,!0),m=i.useMemo(()=>(u.data?.entries??[]).filter(h=>It(h.ts)&&!h.ok).length,[u.data]);return e.jsxs("nav",{className:"nav-rail",children:[e.jsx("div",{className:"rail-logo",title:"MCP Documentor",children:e.jsx(El,{size:18})}),e.jsx(Oa,{variant:"rail",onOpenSettings:a}),e.jsx("div",{className:"rail-sep"}),e.jsx(Se,{icon:Ml,label:"Documentation",active:t==="docs",onClick:()=>s("docs")}),e.jsx(Se,{icon:at,label:"Search ⌘K",active:t==="search",onClick:()=>s("search")}),e.jsx(Se,{icon:Ll,label:c>0?`Outdated · ${c}`:"Outdated",active:t==="outdated",onClick:()=>s("outdated"),children:c>0&&e.jsx("span",{className:"rail-badge rail-badge--warn",children:c})}),e.jsx(Se,{icon:Qn,label:"Recent",active:t==="recent",onClick:()=>s("recent")}),e.jsx(Se,{icon:Ul,label:"Export bundles",active:t==="exports",onClick:()=>s("exports")}),e.jsx(Se,{icon:Mt,label:d>0?`Publications · ${d} unread comments`:"Publications",active:t==="publications",onClick:()=>s("publications"),children:d>0&&e.jsx("span",{className:"rail-badge rail-badge--accent",children:d})}),e.jsx("div",{className:"rail-sep"}),e.jsx(Se,{icon:ka,label:m>0?`Logs · ${m} failed today`:"Logs",active:t==="logs",onClick:()=>s("logs"),children:m>0&&e.jsx("span",{className:"rail-dot"})}),e.jsx("div",{className:"rail-spacer"}),e.jsx(Zi,{}),e.jsx(Se,{icon:$a,label:"Settings",active:!1,onClick:n})]})}function tc({onClose:t,onShowMigrationReport:s}){const{readOnly:n,bumpCommentsVersion:a}=X(),[o,r]=i.useState(!1),[l,c]=i.useState(""),[d,u]=i.useState(null),[m,h]=i.useState(""),[p,f]=i.useState(null),[k,v]=i.useState(""),[g,y]=i.useState(""),[N,j]=i.useState("text-embedding-3-small"),[b,E]=i.useState(100);i.useEffect(()=>{const x=localStorage.getItem("printScale");x&&E(Number(x)),Fa().then(P=>r(!!P)).catch(()=>{}),oi().then(P=>h(P.default??"")).catch(()=>{}),qo().then(P=>c(String(P))).catch(P=>u({ok:!1,text:P.message})),fetch("/api/config").then(P=>P.json()).then(P=>{P.dataDir&&v(P.dataDir),P.model&&j(P.model)}).catch(()=>{})},[]);const D=async(x,P)=>{await fetch("/api/configurations/apply",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:x,value:P})})},$=async()=>{f(null);try{const{path:x}=await ri(m);h(x??""),f({ok:!0,text:x?"Saved":"Removed"})}catch(x){f({ok:!1,text:x.message})}},w=async()=>{u(null);try{const x=await Go(Number(l));c(String(x)),u({ok:!0,text:"Saved"}),a()}catch(x){u({ok:!1,text:x.message})}},S=()=>{localStorage.setItem("printScale",String(b))},I=async()=>{await D("DATA_DIR",k),g&&await D("MCP_DOCUMENTOR_OPENAI_API_KEY",g),await D("MCP_DOCUMENTOR_OPENAI_MODEL",N),t()};return e.jsx("div",{className:"settings-overlay",onClick:t,children:e.jsxs("div",{className:"settings-popover",onClick:x=>x.stopPropagation(),children:[e.jsx("h2",{className:"settings-title",children:"Settings"}),e.jsxs("div",{className:"settings-field",children:[e.jsx("label",{className:"settings-label",children:"Data Directory"}),e.jsx("input",{className:"settings-input",type:"text",value:k,onChange:x=>v(x.target.value),placeholder:"Required"})]}),e.jsxs("div",{className:"settings-field",children:[e.jsx("label",{className:"settings-label",children:"OpenAI API Key"}),e.jsx("input",{className:"settings-input",type:"password",value:g,onChange:x=>y(x.target.value),placeholder:"sk-..."})]}),e.jsxs("div",{className:"settings-field",children:[e.jsx("label",{className:"settings-label",children:"Embedding Model"}),e.jsx("input",{className:"settings-input",type:"text",value:N,onChange:x=>j(x.target.value)})]}),e.jsxs("div",{className:"settings-field",children:[e.jsx("label",{className:"settings-label",children:"Print Scale (%)"}),e.jsxs("div",{style:{display:"flex",gap:"8px",alignItems:"center"},children:[e.jsx("input",{className:"settings-input",type:"number",min:30,max:150,value:b,onChange:x=>E(Number(x.target.value)),style:{width:"80px"}}),e.jsx("button",{className:"settings-save-btn",onClick:S,children:"Apply"})]})]}),e.jsxs("div",{className:"settings-field",children:[e.jsx("label",{className:"settings-label",children:"Default code root (this machine)"}),e.jsxs("div",{style:{display:"flex",gap:"8px",alignItems:"center"},children:[e.jsx("input",{className:"settings-input",type:"text",value:m,disabled:n,onChange:x=>h(x.target.value),placeholder:"Absolute path — used by projects without their own root"}),!n&&e.jsx("button",{className:"settings-save-btn",onClick:$,children:"Apply"})]}),p&&e.jsx("span",{className:`settings-hint${p.ok?"":" error"}`,children:p.text})]}),e.jsxs("div",{className:"settings-field",children:[e.jsx("label",{className:"settings-label",children:"Comments per published document"}),e.jsxs("div",{style:{display:"flex",gap:"8px",alignItems:"center"},children:[e.jsx("input",{className:"settings-input",type:"number",min:1,max:500,value:l,disabled:n,onChange:x=>c(x.target.value),style:{width:"80px"}}),!n&&e.jsx("button",{className:"settings-save-btn",onClick:w,children:"Apply"})]}),e.jsx("span",{className:"settings-hint",children:"Replies included. A document already above the limit keeps its comments and accepts no new one."}),d&&e.jsx("span",{className:`settings-hint${d.ok?"":" error"}`,children:d.text})]}),o&&e.jsxs("div",{className:"settings-field",children:[e.jsx("label",{className:"settings-label",children:"Code sources"}),e.jsx("button",{className:"settings-link-btn",onClick:s,children:"View the environment variables migration report"})]}),e.jsxs("div",{className:"settings-actions",children:[e.jsx("button",{className:"settings-cancel-btn",onClick:t,children:"Cancel"}),!n&&e.jsx("button",{className:"settings-save-btn",onClick:I,children:"Save"})]})]})})}function sc({value:t,onChange:s,options:n}){const[a,o]=i.useState(!1),[r,l]=i.useState(-1),c=i.useRef(null),d=i.useMemo(()=>{const h=t.trim().toLowerCase();return h?n.filter(p=>p.toLowerCase().includes(h)):n},[n,t]);i.useEffect(()=>{if(!a)return;const h=p=>{c.current&&!c.current.contains(p.target)&&o(!1)};return document.addEventListener("mousedown",h),()=>document.removeEventListener("mousedown",h)},[a]),i.useEffect(()=>{l(-1)},[t,a]);const u=h=>{s(h),o(!1)},m=h=>{h.key==="ArrowDown"?(h.preventDefault(),a||o(!0),l(p=>Math.min(p+1,d.length-1))):h.key==="ArrowUp"?(h.preventDefault(),l(p=>Math.max(p-1,0))):h.key==="Enter"&&a&&r>=0&&d[r]?(h.preventDefault(),u(d[r])):h.key==="Escape"&&o(!1)};return e.jsxs("div",{className:"folder-combobox",ref:c,children:[e.jsx("input",{className:"settings-input",value:t,onChange:h=>{s(h.target.value),a||o(!0)},onFocus:()=>o(!0),onKeyDown:m,placeholder:"optional, e.g. backend/auth or backend/auth/new-subfolder",autoComplete:"off",spellCheck:!1}),e.jsx("button",{type:"button",className:"folder-combobox-toggle",onClick:()=>o(h=>!h),tabIndex:-1,"aria-label":"Toggle folder list",children:"▾"}),a&&e.jsxs("div",{className:"folder-combobox-menu",children:[e.jsx("div",{className:"folder-combobox-header",children:"Existing folders"}),d.length===0?e.jsx("div",{className:"folder-combobox-empty",children:n.length===0?"No folder yet — type a path to create one.":"No match — will create a new folder."}):e.jsx("ul",{className:"folder-combobox-list",children:d.map((h,p)=>e.jsx("li",{className:`folder-combobox-item${p===r?" active":""}`,onMouseDown:f=>{f.preventDefault(),u(h)},onMouseEnter:()=>l(p),children:h},h))})]})]})}function nc({onClose:t}){const s=re(),{currentProject:n,projects:a,docs:o}=X(),[r,l]=i.useState(n),[c,d]=i.useState(""),[u,m]=i.useState(""),[h,p]=i.useState(""),[f,k]=i.useState(""),[v,g]=i.useState(!1),[y,N]=i.useState(null),[j,b]=i.useState(null),E=i.useMemo(()=>{const w=new Set;for(const S of o)if(S.folder){const I=S.folder.split("/").filter(Boolean);for(let x=1;x<=I.length;x++)w.add(I.slice(0,x).join("/"))}return Array.from(w).sort()},[o]);i.useEffect(()=>{if(r===n){b(null);return}let w=!1;return fetch(`/api/folders?project=${encodeURIComponent(r)}`).then(S=>S.json()).then(S=>{w||(Array.isArray(S?.folders)?b(S.folders):b([]))}).catch(()=>{w||b([])}),()=>{w=!0}},[r,n]);const D=r===n?E:j??[],$=async()=>{if(!c.trim()||!f.trim()){N("Title and content are required");return}g(!0),N(null);try{const w=h.split(",").map(x=>x.trim()).filter(Boolean),S=await fetch("/api/doc",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({title:c.trim(),content:f,folder:u.trim()||void 0,tags:w.length?w:void 0,project:r})}),I=await S.json();if(!S.ok||I.error)throw new Error(I.error||"Create failed");t(),I.id&&r===n&&s(ne(n,I.id))}catch(w){N(w instanceof Error?w.message:"Create failed")}finally{g(!1)}};return e.jsx("div",{className:"settings-overlay",onClick:t,children:e.jsxs("div",{className:"settings-popover create-doc-popover",onClick:w=>w.stopPropagation(),children:[e.jsx("h2",{className:"settings-title",children:"New document"}),e.jsxs("div",{className:"create-doc-grid",children:[e.jsxs("div",{className:"settings-field",children:[e.jsx("label",{className:"settings-label",children:"Project"}),e.jsx("select",{className:"settings-input",value:r,onChange:w=>l(w.target.value),children:a.map(w=>e.jsxs("option",{value:w,children:[w,w===n?" (current)":""]},w))})]}),e.jsxs("div",{className:"settings-field",children:[e.jsx("label",{className:"settings-label",children:"Title *"}),e.jsx("input",{className:"settings-input",value:c,onChange:w=>d(w.target.value)})]}),e.jsxs("div",{className:"settings-field",children:[e.jsx("label",{className:"settings-label",children:"Folder"}),e.jsx(sc,{value:u,onChange:m,options:D}),e.jsx("div",{className:"create-doc-hint",children:"Pick from the existing tree or type a new path to add a sub-folder."})]}),e.jsxs("div",{className:"settings-field",children:[e.jsx("label",{className:"settings-label",children:"Tags"}),e.jsx("input",{className:"settings-input",value:h,onChange:w=>p(w.target.value),placeholder:"comma, separated, tags"})]})]}),e.jsxs("div",{className:"settings-field create-doc-content-field",children:[e.jsx("label",{className:"settings-label",children:"Content *"}),e.jsx("textarea",{className:"doc-editor-textarea create-doc-textarea",value:f,onChange:w=>k(w.target.value),spellCheck:!1,placeholder:`# My new document
5
5
 
6
6
  Write Markdown here…`})]}),e.jsxs("div",{className:"settings-actions",children:[y&&e.jsx("span",{className:"doc-editor-error",style:{marginRight:"auto"},children:y}),e.jsx("button",{className:"settings-cancel-btn",onClick:t,disabled:v,children:"Cancel"}),e.jsx("button",{className:"settings-save-btn",onClick:$,disabled:v,children:v?"Creating…":"Create"})]})]})})}const nn=400,ac=350,oc=300,rc=/^(https?:\/\/github\.com\/|git@github\.com:)?[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+(\.git)?(#.+)?$/i;function lc(t){const s=Math.max(0,(Date.now()-new Date(t).getTime())/1e3);if(Number.isNaN(s))return"";if(s<60)return"just now";const n=[[3600*24*365,"year"],[3600*24*30,"month"],[3600*24,"day"],[3600,"hour"],[60,"minute"]];for(const[a,o]of n)if(s>=a){const r=Math.floor(s/a);return`${r} ${o}${r>1?"s":""} ago`}return""}function ic({project:t,onClose:s}){const{readOnly:n}=X(),[a,o]=i.useState(null),[r,l]=i.useState("local"),[c,d]=i.useState(""),[u,m]=i.useState({state:"idle"}),[h,p]=i.useState(""),[f,k]=i.useState(""),[v,g]=i.useState({state:"idle"}),[y,N]=i.useState({state:"idle"}),[j,b]=i.useState({state:"loading"}),[E,D]=i.useState(!1),[$,w]=i.useState(null),S=i.useRef(null),[I,x]=i.useState(""),[P,F]=i.useState({state:"idle"}),[B,W]=i.useState(!1),[G,L]=i.useState(0);i.useEffect(()=>{let M=!1;return za().then(U=>{if(M)return;const K=U.find(J=>J.project===t)??{project:t};o(K),K.codeRootOrigin==="project"&&K.codeRoot&&d(K.codeRoot),K.config?.kind==="github"&&(l("github"),p(K.config.repo),k(K.config.branch??""))}).catch(U=>!M&&o({project:t,error:U.message})),li().then(U=>!M&&b({state:"done",value:U})).catch(U=>!M&&b({state:"failed",error:U.message})),()=>{M=!0}},[t]),i.useEffect(()=>{const M=U=>{U.key==="Escape"&&s()};return window.addEventListener("keydown",M),()=>window.removeEventListener("keydown",M)},[s]),i.useEffect(()=>{if(r!=="local"||c.trim()===""){m({state:"idle"});return}const M=new AbortController;m({state:"loading"});const U=setTimeout(()=>{ai(c.trim(),M.signal).then(K=>m({state:"done",value:K})).catch(K=>{K.name!=="AbortError"&&m({state:"failed",error:K.message})})},nn);return()=>{clearTimeout(U),M.abort()}},[r,c]),i.useEffect(()=>{const M=I.trim();if(M.replace("/","").length<2){F({state:"idle"});return}const U=new AbortController;F({state:"loading"});const K=setTimeout(()=>{ei(M,U.signal).then(J=>{F({state:"done",value:J}),L(0)}).catch(J=>{J.name!=="AbortError"&&F({state:"failed",error:J.message})})},ac);return()=>{clearTimeout(K),U.abort()}},[I]);const q=B&&!(P.state==="done"&&P.value.some(M=>M.fullName.toLowerCase()===h.trim().toLowerCase()));i.useEffect(()=>{if(q)return;if(r!=="github"||!rc.test(h.trim())){g({state:"idle"}),S.current=null;return}const M=S.current;if(M&&M.repo===h&&M.branch===f)return;const U=new AbortController;g({state:"loading"});const K=setTimeout(()=>{ti(h.trim(),f||void 0,U.signal).then(J=>{g({state:"done",value:J});const fe=J.ok&&!f?J.branch:f;S.current={repo:h,branch:fe},fe!==f&&k(fe)}).catch(J=>{J.name!=="AbortError"&&g({state:"failed",error:J.message})})},nn);return()=>{clearTimeout(K),U.abort()}},[r,h,f,q]);const T=c.trim()===""||u.state==="done"&&u.value.ok,V=i.useMemo(()=>r==="local"?T?{kind:"local"}:null:v.state!=="done"||!v.value.ok?null:{kind:"github",repo:v.value.repo.fullName,branch:v.value.branch},[r,v,T]),Y=r==="local"?c.trim():void 0,be=V?JSON.stringify([V,Y]):null;i.useEffect(()=>{if(!V){N({state:"idle"});return}const M=new AbortController;N({state:"loading"});const U=setTimeout(()=>{si(t,V,Y,M.signal).then(K=>N({state:"done",value:K})).catch(K=>{K.name!=="AbortError"&&N({state:"failed",error:K.message})})},oc);return()=>{clearTimeout(U),M.abort()}},[t,be]);const ue=M=>{p(M),k(""),x(M),W(!0)},Ue=M=>{p(M),k(""),x(""),W(!1)},ye=P.state==="done"?P.value:[],$e=B&&P.state!=="idle",Ne=M=>{$e&&(M.key==="ArrowDown"?(M.preventDefault(),L(U=>Math.min(ye.length-1,U+1))):M.key==="ArrowUp"?(M.preventDefault(),L(U=>Math.max(0,U-1))):M.key==="Enter"&&ye[G]?(M.preventDefault(),Ue(ye[G].fullName)):M.key==="Escape"&&(M.stopPropagation(),W(!1)))},ot=async()=>{if(V){D(!0),w(null);try{await ni(t,V,Y),s()}catch(M){w(M.message),D(!1)}}},Re=a?.defaultCodeRoot??(a?.codeRootOrigin==="default"?a.codeRoot:void 0),He=u.state==="failed"?u.error:u.state==="done"&&!u.value.ok?u.value.error:null,te=v.state==="done"?v.value:null,pe=te?.repo,he=te?.branches??[],Pe=v.state==="failed"?v.error:te&&!te.ok&&te.field==="repo"?te.error:null,De=$e?null:Pe,Me=te&&!te.ok&&te.field==="branch"?te.error:null,we=f&&!he.includes(f)?[f,...he]:he;return e.jsx("div",{className:"modal-overlay",onClick:s,children:e.jsxs("div",{className:"project-settings",onClick:M=>M.stopPropagation(),role:"dialog","aria-label":"Project settings",children:[e.jsxs("header",{className:"ps-header",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"ps-title",children:"Project settings"}),e.jsxs("div",{className:"ps-subtitle",children:[e.jsx(ca,{size:13}),t]})]}),e.jsx("button",{className:"ps-close",onClick:s,title:"Close (Esc)",children:e.jsx(pn,{size:18})})]}),e.jsxs("div",{className:"ps-body",children:[a?.error&&!a.config&&e.jsxs("div",{className:"ps-alert error",children:[e.jsx(Dl,{size:14}),e.jsxs("span",{children:["The saved settings cannot be read: ",a.error,". Applying replaces them."]})]}),e.jsx("div",{className:"ps-section-label",children:"Where is the code read from?"}),e.jsxs("div",{className:"ps-modes",role:"radiogroup",children:[e.jsxs("button",{className:`ps-mode${r==="local"?" selected":""}`,role:"radio","aria-checked":r==="local",disabled:n,onClick:()=>l("local"),children:[e.jsx(ys,{size:16,className:"ps-mode-icon"}),e.jsxs("span",{className:"ps-mode-text",children:[e.jsx("span",{className:"ps-mode-title",children:"Local working copy"}),e.jsx("span",{className:"ps-mode-desc",children:"Current checkout, uncommitted work included"})]}),r==="local"&&e.jsx(Xe,{size:16,className:"ps-mode-check"})]}),e.jsxs("button",{className:`ps-mode${r==="github"?" selected":""}`,role:"radio","aria-checked":r==="github",disabled:n,onClick:()=>l("github"),children:[e.jsx(bs,{size:16,className:"ps-mode-icon"}),e.jsxs("span",{className:"ps-mode-text",children:[e.jsx("span",{className:"ps-mode-title",children:"GitHub repository"}),e.jsx("span",{className:"ps-mode-desc",children:"Published code of one branch"})]}),r==="github"&&e.jsx(Xe,{size:16,className:"ps-mode-check"})]})]}),r==="local"&&e.jsxs("label",{className:"ps-field",children:[e.jsx("span",{className:"ps-label",children:"Code root on this machine"}),e.jsxs("span",{className:`ps-input-wrap${He?" invalid":""}`,children:[e.jsx(Tt,{size:14,className:"ps-input-icon"}),e.jsx("input",{className:"ps-input",value:c,placeholder:Re?`Machine default: ${Re}`:"Absolute path of the repository",autoFocus:!0,disabled:n,onChange:M=>d(M.target.value)}),u.state==="loading"&&e.jsx(Jt,{size:14,className:"ps-input-status spinning"}),u.state==="done"&&u.value.ok&&e.jsx(Xe,{size:14,className:"ps-input-status ok"}),!n&&c!==""&&e.jsx("button",{type:"button",className:"ps-link muted ps-input-action",onClick:()=>d(""),children:"Use default"})]}),He?e.jsx("span",{className:"ps-help error",children:He}):c.trim()!==""?u.state==="done"?e.jsx("span",{className:"ps-help ok",children:"Folder found · used by this project only, on this machine"}):e.jsx("span",{className:"ps-help",children:"Checked as you type."}):Re?e.jsx("span",{className:"ps-help",children:"Uses the machine default. Stored on this machine only, never synced."}):e.jsx("span",{className:"ps-help",children:"No code root on this machine: only tracked files stored with an absolute path can be read."})]}),r==="github"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"ps-field",children:[e.jsx("label",{className:"ps-label",htmlFor:"ps-repo-input",children:"Repository"}),e.jsxs("div",{className:"ps-combobox",children:[e.jsxs("span",{className:`ps-input-wrap${De?" invalid":""}`,children:[pe?e.jsx(wt,{size:14,className:"ps-input-icon"}):e.jsx(at,{size:14,className:"ps-input-icon"}),e.jsx("input",{id:"ps-repo-input",className:"ps-input",value:h,placeholder:"Search a repository, or paste owner/repo",autoFocus:!0,autoComplete:"off",disabled:n,role:"combobox","aria-expanded":$e,"aria-controls":"ps-repo-suggestions",onChange:M=>ue(M.target.value),onKeyDown:Ne,onFocus:()=>W(!0),onBlur:()=>W(!1)}),(v.state==="loading"||P.state==="loading")&&e.jsx(Jt,{size:14,className:"ps-input-status spinning"}),v.state!=="loading"&&P.state!=="loading"&&pe&&!De&&e.jsx(Xe,{size:14,className:"ps-input-status ok"})]}),$e&&e.jsxs("ul",{className:"ps-suggestions",id:"ps-repo-suggestions",role:"listbox",children:[P.state==="loading"&&e.jsx("li",{className:"ps-suggestion-note",children:"Searching…"}),P.state==="failed"&&e.jsx("li",{className:"ps-suggestion-note error",children:P.error}),P.state==="done"&&ye.length===0&&e.jsx("li",{className:"ps-suggestion-note",children:"No repository found"}),ye.map((M,U)=>e.jsxs("li",{role:"option","aria-selected":U===G,className:`ps-suggestion${U===G?" highlighted":""}`,onMouseEnter:()=>L(U),onMouseDown:K=>{K.preventDefault(),Ue(M.fullName)},children:[e.jsxs("span",{className:"ps-suggestion-name",children:[M.private?e.jsx(Ol,{size:12}):e.jsx(wt,{size:12}),M.fullName]}),M.description&&e.jsx("span",{className:"ps-suggestion-desc",children:M.description})]},M.fullName))]})]}),De?e.jsx("span",{className:"ps-help error",children:De}):pe?e.jsxs("span",{className:"ps-help ok",children:["Found · ",pe.private?"private":"public"," · default branch ",pe.defaultBranch]}):e.jsxs("span",{className:"ps-help",children:["Searched as you type",j.state==="done"&&j.value.configured?", private repositories included":"","."]})]}),e.jsxs("label",{className:"ps-field",children:[e.jsx("span",{className:"ps-label",children:"Branch"}),e.jsxs("span",{className:`ps-input-wrap${Me?" invalid":""}`,children:[e.jsx(Il,{size:14,className:"ps-input-icon"}),e.jsxs("select",{className:"ps-input ps-select",value:f,disabled:n||we.length===0,onChange:M=>k(M.target.value),children:[we.length===0&&e.jsx("option",{value:"",children:"—"}),we.map(M=>e.jsxs("option",{value:M,children:[M,M===pe?.defaultBranch?" (default)":""]},M))]}),f&&f===pe?.defaultBranch&&e.jsx("span",{className:"ps-chip",children:"default"})]}),Me?e.jsx("span",{className:"ps-help error",children:Me}):te?.ok?e.jsxs("span",{className:"ps-help",children:["Head ",te.head.sha.slice(0,7)," · ",te.head.message," · ",lc(te.head.date)]}):null]}),e.jsxs("div",{className:"ps-field",children:[e.jsx("span",{className:"ps-label",children:"GitHub access"}),e.jsxs("span",{className:"ps-token",children:[e.jsx(Fl,{size:14,className:`ps-token-icon${j.state==="done"&&j.value.login?" ok":j.state==="done"&&j.value.error?" error":""}`}),e.jsxs("span",{className:"ps-token-text",children:[j.state==="loading"&&"Checking the token…",j.state==="failed"&&j.error,j.state==="done"&&(j.value.configured?j.value.login?`${j.value.variable} · connected as ${j.value.login}`:`${j.value.variable} rejected — ${j.value.error}`:`${j.value.variable} is not set · public repositories only`)]})]}),e.jsx("span",{className:"ps-help",children:"Set in the MCP server's environment variables only — not editable here."})]})]}),y.state!=="idle"&&e.jsxs("div",{className:`ps-preview${y.state==="failed"||y.state==="done"&&y.value.sourceError?" error":""}`,children:[y.state==="loading"?e.jsx(Jt,{size:16,className:"ps-preview-icon spinning"}):e.jsx(Bl,{size:16,className:"ps-preview-icon"}),e.jsxs("div",{className:"ps-preview-text",children:[y.state==="loading"&&e.jsx("span",{className:"ps-preview-title",children:"Checking the docs against this source…"}),y.state==="failed"&&e.jsx("span",{className:"ps-preview-title",children:y.error}),y.state==="done"&&e.jsxs(e.Fragment,{children:[e.jsxs("span",{className:"ps-preview-title",children:["Checked against ",y.value.label," — ",y.value.docs," doc",y.value.docs===1?"":"s"]}),e.jsx("span",{className:"ps-preview-counts",children:y.value.sourceError?y.value.sourceError:[`${y.value.upToDate} up to date`,`${y.value.stale} would be outdated`,`${y.value.unverifiable} unverifiable`,...y.value.broken>0?[`${y.value.broken} with broken tracking`]:[]].join(" · ")})]})]})]})]}),e.jsxs("footer",{className:"ps-footer",children:[e.jsxs("div",{className:"ps-footer-note",children:[e.jsx(zl,{size:14}),e.jsxs("span",{children:["Source saved with the docs, shared across machines.",e.jsx("br",{}),"Applied at once — no restart."]})]}),$&&e.jsx("span",{className:"ps-help error ps-save-error",children:$}),e.jsx("button",{className:"ps-btn",onClick:s,children:"Cancel"}),!n&&e.jsx("button",{className:"ps-btn primary",onClick:ot,disabled:!V||E,children:E?"Applying…":"Apply"})]})]})})}function cc({entry:t}){return t.status!=="imported"?e.jsx(Ns,{size:14,className:"mig-icon warn"}):t.kind==="code-root"?e.jsx(Tt,{size:14,className:"mig-icon"}):t.kind==="local"?e.jsx(ys,{size:14,className:"mig-icon"}):e.jsx(bs,{size:14,className:"mig-icon accent"})}function dc({onClose:t,onReviewProject:s}){const[n,a]=i.useState(null),[o,r]=i.useState(null),[l,c]=i.useState(!1);i.useEffect(()=>{Fa().then(a).catch(h=>r(h.message))},[]);const d=h=>{ii().catch(()=>{}).finally(()=>{t(),h?.()})};i.useEffect(()=>{const h=p=>{p.key==="Escape"&&d()};return window.addEventListener("keydown",h),()=>window.removeEventListener("keydown",h)},[]);const u=async()=>{if(n)try{await navigator.clipboard.writeText(n.variables.join(`
7
7
  `)),c(!0),setTimeout(()=>c(!1),1500)}catch{}},m=n?.entries.find(h=>h.status==="imported"&&h.project)?.project;return e.jsx("div",{className:"modal-overlay",onClick:()=>d(),children:e.jsxs("div",{className:"migration-report",onClick:h=>h.stopPropagation(),role:"dialog","aria-label":"Code source settings imported",children:[e.jsxs("header",{className:"mig-header",children:[e.jsx("span",{className:"mig-badge",children:e.jsx(_l,{size:18})}),e.jsxs("div",{children:[e.jsx("h2",{className:"mig-title",children:"Code source settings imported"}),e.jsx("p",{className:"mig-subtitle",children:"Found in this server's environment. They now live in each project's settings."})]})]}),o&&e.jsx("div",{className:"ps-alert error mig-error",children:o}),n&&e.jsxs(e.Fragment,{children:[n.entries.length>0&&e.jsxs("table",{className:"mig-table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Project"}),e.jsx("th",{children:"Now configured as"}),e.jsx("th",{children:"From"})]})}),e.jsx("tbody",{children:n.entries.map((h,p)=>e.jsxs("tr",{className:h.status!=="imported"?"not-imported":void 0,children:[e.jsx("td",{className:h.project?void 0:"mig-scope",children:h.project??"This machine"}),e.jsx("td",{children:e.jsxs("span",{className:"mig-source",children:[e.jsx(cc,{entry:h}),h.detail]})}),e.jsx("td",{className:"mig-from",children:h.from})]},p))})]}),e.jsxs("div",{className:"mig-callout",children:[e.jsxs("div",{className:"mig-callout-text",children:[e.jsx("span",{className:"mig-callout-title",children:"These variables are no longer read"}),e.jsx("span",{className:"mig-callout-desc",children:"Remove them from the env block of .mcp.json. Until then, the server ignores them and says so in its log."}),e.jsx("pre",{className:"mig-vars",children:n.variables.join(`
@@ -5,7 +5,7 @@
5
5
  <link rel="icon" type="image/svg+xml" href="./vite.svg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>MCP Documentor</title>
8
- <script type="module" crossorigin src="./assets/main-BTLYod5c.js"></script>
8
+ <script type="module" crossorigin src="./assets/main-DqmdvCbr.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="./assets/DocContent-D5CLsUKq.js">
10
10
  <link rel="stylesheet" crossorigin href="./assets/DocContent-BxncLHIS.css">
11
11
  <link rel="stylesheet" crossorigin href="./assets/main-BhezOZ_3.css">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imenam/mcp-documentor",
3
- "version": "1.0.104",
3
+ "version": "1.0.105",
4
4
  "main": "dist/src/index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",
@@ -11,33 +11,32 @@
11
11
  * (doc://old-slug#h) → (doc://folder/old-slug#h)
12
12
  *
13
13
  * Usage:
14
- * node scripts/migrate-links.js [--dry-run] [--data-dir /path/to/.docs-data]
14
+ * node scripts/migrate-links.js [--dry-run] [--data-dir /path/to/data]
15
15
  *
16
16
  * Options:
17
17
  * --dry-run Show what would be changed without modifying any file.
18
- * --data-dir Override the data directory (default: <project-root>/.docs-data).
18
+ * --data-dir Data directory. Without it, the DATA_DIR variable is used.
19
19
  */
20
20
 
21
21
  import fs from "fs";
22
22
  import path from "path";
23
- import { fileURLToPath } from "url";
24
23
  import matter from "gray-matter";
25
24
 
26
25
  // ---------------------------------------------------------------------------
27
26
  // Setup
28
27
  // ---------------------------------------------------------------------------
29
28
 
30
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
31
- const rootDir = path.join(__dirname, "..");
32
-
33
29
  const args = process.argv.slice(2);
34
30
  const dryRun = args.includes("--dry-run");
35
31
 
36
32
  const dataDirArgIdx = args.indexOf("--data-dir");
37
- const dataDir =
38
- dataDirArgIdx !== -1 && args[dataDirArgIdx + 1]
39
- ? args[dataDirArgIdx + 1]
40
- : path.join(rootDir, ".docs-data");
33
+ const rawDataDir =
34
+ dataDirArgIdx !== -1 && args[dataDirArgIdx + 1] ? args[dataDirArgIdx + 1] : process.env.DATA_DIR?.trim();
35
+ if (!rawDataDir) {
36
+ console.error("[ERROR] DATA_DIR is not set and no --data-dir was given. It is the folder where the documentation projects are stored.");
37
+ process.exit(1);
38
+ }
39
+ const dataDir = path.resolve(rawDataDir);
41
40
 
42
41
  // ---------------------------------------------------------------------------
43
42
  // Helpers
@@ -18,14 +18,14 @@
18
18
  * A tracked file whose absolute path is NOT under the project's code root is
19
19
  * left absolute and reported, so nothing is silently broken.
20
20
  *
21
- * The data dir is resolved like the server: --data-dir flag, else MCP_DATA_DIR,
22
- * else <package>/data. The MCP_DATA_DIR fallback is what makes npx usable.
21
+ * The data dir is the --data-dir flag, else the DATA_DIR variable read by the
22
+ * server. Without either, the script stops.
23
23
  *
24
24
  * Usage (from a clone):
25
25
  * node scripts/migrate-paths-to-relative.js [--dry-run] [--data-dir <dir>]
26
26
  *
27
27
  * Usage (npx install — no clone):
28
- * MCP_DATA_DIR="<your data dir>" \
28
+ * DATA_DIR="<your data dir>" \
29
29
  * npx -p @imenam/mcp-documentor mcp-documentor-migrate-paths --dry-run
30
30
  *
31
31
  * This migration is a ONE-TIME operation: run it once on the machine where the
@@ -44,17 +44,15 @@ const rootDir = path.join(__dirname, "..");
44
44
  const args = process.argv.slice(2);
45
45
  const dryRun = args.includes("--dry-run");
46
46
 
47
- // Data dir resolution mirrors the server (StorageEngine.getDataDir):
48
- // --data-dir flag > MCP_DATA_DIR env > <package>/data fallback.
49
- // The env fallback is what makes `npx` work: the data lives in the user's
50
- // MCP_DATA_DIR, not inside the npx package cache.
47
+ // Data dir: --data-dir flag, else the DATA_DIR variable read by the server.
51
48
  const dataDirArgIdx = args.indexOf("--data-dir");
52
- const dataDir =
53
- dataDirArgIdx !== -1 && args[dataDirArgIdx + 1]
54
- ? args[dataDirArgIdx + 1]
55
- : process.env.MCP_DATA_DIR && process.env.MCP_DATA_DIR.trim() !== ""
56
- ? process.env.MCP_DATA_DIR.trim()
57
- : path.join(rootDir, "data");
49
+ const rawDataDir =
50
+ dataDirArgIdx !== -1 && args[dataDirArgIdx + 1] ? args[dataDirArgIdx + 1] : process.env.DATA_DIR?.trim();
51
+ if (!rawDataDir) {
52
+ console.error("[ERROR] DATA_DIR is not set and no --data-dir was given. It is the folder where the documentation projects are stored.");
53
+ process.exit(1);
54
+ }
55
+ const dataDir = path.resolve(rawDataDir);
58
56
 
59
57
  // ---------------------------------------------------------------------------
60
58
  // Reuse the compiled resolver so migration matches runtime behaviour exactly.